英和訓練

著作権は原文に属します

Learn Clojure - Sequential Collections シーケンシャルなコレクション

Clojure collections "collect" values into compound values. Clojureのコレクションとは、任意個の値を集めて(コレクトして)、1つの複合的な値としたものだ。There are four key Clojure collection types: vectors, lists, sets, and maps. Clojureにおいて重要なコレクション型は、ベクタ、リスト、セット、マップの4つである。Of those four collection types, vectors, and lists are ordered. これら4つのコレクション型のうち、ベクタとリストは順序のあるコレクションである。

Vectors ベクタ

Vectors are an indexed, sequential data structure. ベクタは整数の添字を持つ、シーケンシャルなデータ構造だ。Vectors are represented with [ ] like this: ベクタは次のように[ ]を使って表される。

[1 2 3]

Indexed access 添字によるアクセス

"Indexed" means that elements of a vector can be retrieved by index. 「添字を持つ」とは、添字を指定することでベクタの要素が取り出せるということである。In Clojure (as in Java), indexes start at 0, not 1. (Java同様)Clojureでは、添字は(1ではなく)0から始まる。Use the get function to retrieve an element at an index: ある添字に対応する要素を取り出すには、次のようにget関数を使う。

user=> (get ["abc" false 99] 0)
"abc"
user=> (get ["abc" false 99] 1)
false

Calling get with an invalid index returns nil: 無効な添字とともにgetを呼べばnilが返される。

user=> (get ["abc" false 99] 14)
nil

count

All Clojure collections can be counted: count関数によってClojureの任意のコレクションの要素数を得られる。

user=> (count [1 2 3])
3

Constructing 生成

In addition to the literal [ ] syntax, Clojure vectors can be created with the vector function: [ ]というリテラルな構文で生成する以外にも、vector関数によってもベクタを生成することができる。

user=> (vector 1 2 3)
[1 2 3]

Adding elements 要素の追加

Elements are added to a vector with conj (short for conjoin). conjoin(繋げる)という意味のconj関数を使えば要素をベクタに追加できる。Elements are always added to a vector at the end: ベクタにおいては要素は常に右側に追加される。

user=> (conj [1 2 3] 4 5 6)
[1 2 3 4 5 6]

Immutability 不変性

Clojure collections share important properties of simple values like strings and numbers, such as immutability and equality comparison by value. 文字列や数といったシンプルな値と同じ重要な属性を、Clojureのどのコレクションも共有している。つまり不変であり、値として等しさを比較できる。

For example, lets create a vector and modify it with conj. 例えば、次のようにベクタを作りconjで変更してみよう。

user=> (def v [1 2 3])
#'user/v
user=> (conj v 4 5 6)
[1 2 3 4 5 6]

Here conj returned a new vector but if we examine the original vector, we see it's unchanged: 行ったconjは新しいベクタを返した。しかし元のベクタを見てみると、元のベクタは変更されていないことが確認できる。

user=> v
[1 2 3]

Any function that "changes" a collection returns a new instance. コレクションを「変更する」どの関数も、新しいインスタンスを返す。Your program will need to remember or pass along the changed instance to take advantage of it. 変更を有効にするためには、変更後のインスタンスを保持したり、別の関数に渡して利用したりする必要がある。

Lists リスト

Lists are sequential linked lists that add new elements at the head of the list, instead of at the tail like vectors. リストはシーケンシャルな連結リストであり、ベクタにおいては新要素が右側に追加されたのとは異なり、リストでは左側に追加される。

Constructing 生成

Because lists are evaluated by invoking the first element as a function, we must quote a list to prevent evaluation: リストは第1要素を関数とする呼び出しとして評価されるため、評価をさせないためには'を使ってリストをクォートする必要がある。

(def cards '(10 :ace :jack 9))

Lists are not indexed so they must be walked using first and rest. リストには添字がない。そのため、firstrestを使って要素を辿らねばならない。

user=> (first cards)
10
user=> (rest cards)
'(:ace :jack 9)

Adding elements 要素の追加

conj can be used to add elements to a list just as with vectors. ベクタと同様リストについてもconjによって要素を追加できる。However, conj always adds elements where it can be done in constant time for the data structure. しかし、conjは常に、対象となるデータ構造において定数時間で実現できる方法で要素を追加しようとする。In the case of lists, elements are added at the front: リストの場合は要素は左側に追加される。

user=> (conj cards :queen)
(:queen 10 :ace :jack 9)

Stack access スタックとしてのアクセス

Lists can also be used as a stack with peek and pop: 関数peek(覗く)およびpop(外す)を使うことで、リストを(後入れ先出しの)スタック構造として使うことができる。

user=> (def stack '(:a :b))
#'user/stack
user=> (peek stack)
:a
user=> (pop stack)
(:b)

原文: https://clojure.org/guides/learn/sequential_colls