[1 2 3]
Clojureのコレクション(collection)は値を複合的な値に「集める」(collect)。Clojureのコレクション型には重要なものが4種類ある: ベクター、リスト、セット、マップだ。4種類のコレクション型のうち、ベクターとリストは順序付き(ordered)だ。
ベクターはインデックス付き(indexed)でシーケンシャル(sequential)なデータ型だ。ベクターはこのように [ ]
で表される:
[1 2 3]
「インデックス付き」(indexed)とは、ベクターの要素がインデックスで取得できることを意味する。Clojureでは(Javaと同様に)インデックスは1ではなく0から始まる。要素をインデックスで取得するには
get
を使う:
user=> (get ["abc" false 99] 0)
"abc"
user=> (get ["abc" false 99] 1)
false
無効なインデックスでgetを呼び出すと nil
が返ってくる:
user=> (get ["abc" false 99] 14)
nil
要素は conj
(conjoinの略)を使うことでベクターに追加される。要素は常にベクターの最後に追加される:
user=> (conj [1 2 3] 4 5 6)
[1 2 3 4 5 6]
Clojureコレクションは、イミュータビリティや値による等価性比較といった、文字列や数値などの単純な値と共通して重要な性質を備えている。
例えば、ベクターを作って conj
で変更してみよう。
user=> (def v [1 2 3])
#'user/v
user=> (conj v 4 5 6)
[1 2 3 4 5 6]
ここで conj
は新しいベクターを返すが、もとのベクターを調べてみると変化していないことが分かる:
user=> v
[1 2 3]
コレクションを「変更」するあらゆる関数は新しいインスタンスを返す。これを上手く利用するにはプログラムが変更されたインスタンスを覚えておいたり持ち回ったりする必要があるだろう。
リストはシーケンシャル(sequential)な連結リストであり、ベクターのように末尾ではなくリストの先頭に新しい要素を追加する。
リストは最初の要素を関数として呼び出すことで評価されるので、評価を避けるためにはリストをクォート(quote)しなければならない:
(def cards '(10 :ace :jack 9))
リストはインデックス付き(indexed)ではないので first
と rest
でたどらなければならない。
user=> (first cards)
10
user=> (rest cards)
'(:ace :jack 9)