TL;DR
- Clojure の集合は
#{ }で定義し、要素はユニークでなければならない。 contains?のほか、集合を関数として呼び出しても要素を確かめられる。キーワードの集合なら、キーワードを関数として呼び出すこともできる。
内容
定義
Clojure では次のように定義する。
#{1 2 3 4}type で確かめると、PersistentHashSet であることが分かる。
(type #{1 2 3 4})
;; clojure.lang.PersistentHashSet集合は、要素がユニークでなければならない。
#{1 2 3 4 4}
;; Syntax error reading source at (REPL:X:XX).
;; Duplicate key: 4集合であることの検証
ある値が集合であるかを確かめるには、set? を使う。
(set? #{1 2 3 4}) ;; true要素の検証
contains? を使うと、指定した要素が含まれるかを確かめられる。
(def fruits #{"Apple" "Orange" "Mango" "Banana"})
(contains? fruits "Banana") ;; true
(contains? fruits "Jack Fruit") ;; false次のように確かめることもできる。含まれる場合はその要素自身が、含まれない場合は nil が返ってくる。
(fruits "Banana") ;; "Banana"
(fruits "Jack Fruit") ;; nilこれを逆にすると、文字列は関数ではないので例外が発生する。
("Banana" fruits) ;; Execution error (ClassCastException)キーワードの場合
Clojure には**キーワード**というものがあり、:ruby のように書く。
(def programming-languages #{:ruby :python :clojure})キーワードの集合に対しても、contains? は使える。
(contains? programming-languages :ruby) ;; true
(contains? programming-languages :java) ;; falsecontains? を使わずに確かめることもできる。
(programming-languages :ruby) ;; :rubyただし、キーワードには文字列と比べて特別な性質があり、次のコードも動く。キーワード :ruby を関数として扱い、集合を渡して値を取得している。
(:ruby programming-languages) ;; :ruby要素の追加・削除
conj を使うと、要素を追加できる。ベクタやリストと違い、cons は存在しない。
(conj programming-languages :perl) ;; #{:clojure :python :perl :ruby}disj を使うと、要素を削除できる。
(disj programming-languages :ruby) ;; #{:clojure :python}どちらの操作をしても、元の集合は変わらない(イミュータブル)。
programming-languages ;; #{:clojure :python :ruby}