コンテンツにスキップ

配列 (Array)

Arrayは順番に意味があり整数でインデックスされた、T型の値を要素として持つジェネリックなコレクションです。

配列は通常、角括弧 ([]) とコンマ (,) によって区切られた個々の要素による配列リテラルで生成されます。

[1, 2, 3]

ジェネリック型引数

配列のジェネリック型引数Tはリテラルの要素の型から推論されます。すべての要素が同じ型を持っていた場合、Tはそれに等しくなります。そうでなければ、すべての要素の型のユニオン型となります。

[1, 2, 3]         # => Array(Int32)
[1, "hello", 'x'] # => Array(Int32 | String | Char)

閉じ角括弧のあとに続けてofと型を置くことで、明示的に型を指定することもできます。これは推論された型を置き換えるので、生成時には同じ型しか入っていないけれど、あとで別の型が入ってくるような場合に対応できます。

array_of_numbers = [1, 2, 3] of Float64 | Int32 # => Array(Float64 | Int32)
array_of_numbers << 0.5                         # => [1, 2, 3, 0.5]

array_of_int_or_string = [1, 2, 3] of Int32 | String # => Array(Int32 | String)
array_of_int_or_string << "foo"                      # => [1, 2, 3, "foo"]

空の配列リテラルは常に型を指定する必要があります。

[] of Int32 # => Array(Int32).new

パーセント配列リテラル

文字列の配列シンボルの配列をパーセント配列リテラルで生成できます。

%w(one two three) # => ["one", "two", "three"]
%i(one two three) # => [:one, :two, :three]

配列ライクな型のリテラル

Crystal はさらに、配列ライクな型のためのリテラルをサポートしています。型の名前にひげ括弧 ({}) とコンマ (,) によって区切られた個々の要素を続けることで利用できます。

Array{1, 2, 3}

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

IO::Memory{1, 2, 3}
Set{1, 2, 3}

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

array_like = IO::Memory.new
array_like << 1
array_like << 2
array_like << 3

ジェネリック型であるSetに対しては、ジェネリック型 T が配列リテラルと同様の方法で要素の型から推論されます。よって、上の例は以下と等しいものになります。

array_like = Set(typeof(1, 2, 3)).new
array_like << 1
array_like << 2
array_like << 3

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

Set(Int32){1, 2, 3}

Splat Expansion

The splat operator can be used inside array and array-like literals to insert multiple values at once.

[1, *coll, 2, 3]
Set{1, *coll, 2, 3}

The only requirement is that coll's type must include Enumerable. よって、上の例は以下と等しいものになります。

array = Array(typeof(...)).new
array << 1
array.concat(coll)
array << 2
array << 3

array_like = Set(typeof(...)).new
array_like << 1
coll.each do |elem|
  array_like << elem
end
array_like << 2
array_like << 3

In these cases, the generic type argument is additionally inferred using coll's elements.