コンテンツにスキップ

ハッシュ (Hash)

HashK型のキーとV型の値のペアの対応付けからなるジェネリックなコレクションです。

ハッシュは通常、ひげ括弧 ({ }) に囲われた中に、キーと値を => で組にしてコンマ , で区切って並べたものである、ハッシュリテラルによって生成されます。

{"one" => 1, "two" => 2}

ジェネリック型引数

キーの型の K と値の型の V というジェネリック型引数は、それぞれリテラル中のキーと値の型から推論されます。すべて同じ型であれば、KおよびVはそれに等しくなります。そうでなければ、すべてのキーの型のユニオン型ないし値の型のユニオン型となります。

{1 => 2, 3 => 4}   # Hash(Int32, Int32)
{1 => 2, 'a' => 3} # Hash(Int32 | Char, Int32)

閉じひげ括弧のあとに続けてofとキーの型 (K)、さらに => に続けて値の型 (V) を置くことで、明示的に型を指定することもできます。これは推論された型を置き換えるので、初期化時には同じ型のみを持っているが、他の型も受け入れる必要があるようなハッシュを生成したい場合に対応できます。

空のハッシュリテラルは常に型を指定する必要があります。

{} of Int32 => Int32 # => Hash(Int32, Int32).new

ハッシュライクな型のリテラル

Crystal はさらにハッシュライクな型のためのリテラルをサポートしています。型の名前のあとに続けたひげ括弧 ({}) の中に、コンマ区切りのキーと値の組を並べることで利用できます。

Hash{"one" => 1, "two" => 2}

引数を持たないコンストラクタと[]=メソッドを持つ任意の型に対して、この構文は利用できます。

HTTP::Headers{"foo" => "bar"}

ジェネリック型でない型HTTP::Headersに対しては、上の例は以下と等しいものになります。

headers = HTTP::Headers.new
headers["foo"] = "bar"

ジェネリック型の場合、型引数はハッシュリテラルと同様の方法でキーと値の型から推論されます。

MyHash{"foo" => 1, "bar" => "baz"}

ここでMyHashがジェネリック型であれば、上の例は以下と等しいものになります。

my_hash = MyHash(typeof("foo", "bar"), typeof(1, "baz")).new
my_hash["foo"] = 1
my_hash["bar"] = "baz"

型引数は型名の部分で明示的に指定することもできます。

MyHash(String, String | Int32){"foo" => "bar"}