InlineArrayのHashable適合
InlineArray: Hashable
このダイジェストはClaude Opus 4.7 / 4.8によって生成されたものです(License)。原文はこちら↗。
01 何が問題だったのか
SE-0453 で導入された固定サイズ配列 InlineArray は、要素型が Equatable や Hashable に適合していても、それ自身は Equatable にも Hashable にも適合していませんでした。
そのため、次のような何気ない操作ができませんでした。
let a: InlineArray<3, Int> = [1, 2, 3]
let b: InlineArray<3, Int> = [1, 2, 3]
a == b // error: InlineArray は Equatable に適合していない
let set: Set<InlineArray<3, Int>> = [a, b] // error: InlineArray は Hashable に適合していない
Array をはじめとする標準ライブラリの他のコレクションでは、要素型が適合していれば Equatable / Hashable にも適合するのが当たり前です。InlineArray だけこれらの適合を欠いているのは不便で、利用者が自前でエクステンションを書いて補うしかありませんでした。
02 どのように解決されるのか
InlineArray に、要素型 Element が適合しているときだけ成立する条件付きの Equatable / Hashable 適合を追加します。
let a: InlineArray<3, Int> = [1, 2, 3]
let b: InlineArray<3, Int> = [1, 2, 3]
a == b // true
let set: Set<InlineArray<3, Int>> = [a, b] // 要素は 1 つにまとまる
これにより、要素型さえ適合していれば InlineArray を == / != で比較したり、Set の要素や Dictionary のキーとして使ったりできるようになります。
適合の意味
追加される適合は、次のような素直なものです。
- 等値性は、参照の同一性ではなく 要素ごとの比較 で判定されます。同じ位置の要素同士が順に等しければ、2 つの
InlineArrayは等しいとみなされます。 - ハッシュ値の計算には、
InlineArrayの すべての要素 が寄与します。 - 等値比較・ハッシュ計算はいずれも要素数を
nとしてO(n)の計算量です。
なお、等値比較は最初に一致しない要素を見つけた時点で早期に打ち切ってもよいことになっています。つまり InlineArray.== が定数時間である保証はなく、逆に最初の不一致より後ろの要素へアクセスしない保証もありません。定数時間比較が必要な用途(暗号処理など)では、この点に注意してください。
過去のバージョンへのバックデプロイ
プロトコル要件を実装するメソッドは、InlineArray が導入された時点まで遡ってバックデプロイされます。そのため、より新しいOSでしか使えないといった制約はなく、必要であれば利用者が自前で retroactive な適合を宣言することもできます。
これまで自前でエクステンションを書いて Equatable / Hashable 適合を補っていた場合は、(極端に異なるセマンティクスを実装していたのでない限り)そのエクステンションを削除できます。