user=> (map (fn [x] (.toUpperCase x)) (.split "Dasher Dancer Prancer" " "))
("DASHER" "DANCER" "PRANCER")
Clojure 具有豐富的資料結構。它們共用一組屬性
它們是不可變的
它們是可讀的
它們在 equals 的實作中支援適當的值相等語意
它們提供良好的雜湊值
此外,集合
透過介面進行操作。
支援排序
支援持續操作。
支援元資料
實作 java.lang.Iterable
實作 java.util.Collection 或 java.util.Map 的非選用 (唯讀) 部分
nil 是 Clojure 中任何資料類型的可能值。nil 與 Java null 具有相同的值。Clojure 條件系統以 nil 和 false 為基礎,其中 nil 和 false 表示條件測試中的邏輯假值 - 其他任何值都是邏輯真值。此外,nil 用作序列協定中的序列結束哨兵值。
Clojure 預設完全支援 JVM 原生值,允許為數值應用程式編寫高效能、慣用的 Clojure 程式碼。
Clojure 也支援衍生自 java.lang.Number 的 Java 封裝數字類型,包括 BigInteger 和 BigDecimal,以及其自己的 Ratio 類型。有一些特殊處理
預設情況下,Clojure 使用 Java 的 long 原生類型實例來操作自然數。當原生整數運算產生一個值,而該值太大而無法包含在原生值中時,會擲出 java.lang.ArithmeticException。Clojure 提供了一組以撇號為後綴的替代數學運算子:+'、-'、*'、inc' 和 dec'。這些運算子在溢位時會自動提升為 BigInt,但效率低於常規數學運算子。
Clojure 字串是 Java 字串。另請參閱 列印。
user=> (map (fn [x] (.toUpperCase x)) (.split "Dasher Dancer Prancer" " "))
("DASHER" "DANCER" "PRANCER")
所有 Clojure 集合都是不可變且 持續的。特別是,Clojure 集合透過使用結構性共用來支援有效建立「修改過」的版本,並對持續使用做出所有效能界限保證。這些集合是有效率且本質上執行緒安全的。集合由抽象表示,可能有一個或多個具體實現。特別是,由於「修改」操作會產生新的集合,因此新的集合可能與來源集合沒有相同的具體類型,但會有相同的邏輯(介面)類型。
Clojure 提供自己的雜湊運算,為集合(和其他類型)提供更好的雜湊屬性,稱為 hasheq 值。
IHashEq
介面標記提供 hasheq()
函數以取得 hasheq 值的集合。在 Clojure 中,hash 函數可用於計算 hasheq 值。
已排序集合(向量、清單、序列等)必須使用下列演算法來計算 hasheq(其中 hash 計算 hasheq)。請注意,unchecked-add-int 和 unchecked-multiply-int 用於取得整數溢位計算。
(defn hash-ordered [collection]
(-> (reduce (fn [acc e] (unchecked-add-int
(unchecked-multiply-int 31 acc)
(hash e)))
1
collection)
(mix-collection-hash (count collection))))
未排序集合(映射、集合)必須使用下列演算法來計算 hasheq。映射條目視為鍵值的有序集合。請注意,unchecked-add-int 用於取得整數溢位計算。
(defn hash-unordered [collection]
(-> (reduce unchecked-add-int 0 (map hash collection))
(mix-collection-hash (count collection))))
mix-collection-hash 演算法是實作細節,可能會變更。
Map 是一種將鍵對應到值的集合。提供兩種不同的 map 類型 - 哈希和排序。哈希 map 需要正確支援 hashCode 和 equals 的鍵。排序 map 需要實作 Comparable 或 Comparator 執行個體的鍵。哈希 map 提供較快的存取(log32N 跳躍)相對於(logN 跳躍),但排序 map 是經過排序的。count 為 O(1)。conj 預期另一個(可能是單一項目)map 作為項目,並傳回一個新的 map,它是舊的 map 加上新 map 的項目,這可能會覆寫舊的項目。conj 也接受 MapEntry 或兩個項目的向量(鍵和值)。seq 傳回 map 項目序列,它們是鍵/值對。排序 map 也支援 rseq,它傳回反向順序的項目。Map 實作 IFn,用於 invoke() 一個引數(一個鍵)並有一個選用的第二個引數(一個預設值),也就是說,map 是其鍵的函數。nil 鍵和值是可以的。
建立一個新的 map:hash-map sorted-map sorted-map-by
「變更」一個 map:assoc dissoc select-keys merge merge-with zipmap
檢查一個 map:get contains? find keys vals map?
檢查一個 map 項目:key val
現在,大多數 StructMaps 的用途都更適合使用 記錄。 |
通常,許多映射實例具有相同的基礎鍵集,例如在將映射用作結構或物件時,在其他語言中會使用這些結構或物件。StructMaps 支援此用例,方法是有效地共享鍵資訊,同時也提供對這些鍵的效能增強存取器(選用)。StructMaps 在各方面都是映射,支援相同的函數集,可與所有其他映射互通,且可持續擴充(即結構映射不限於其基礎鍵)。唯一的限制是您無法將結構映射與其基礎鍵之一分離。結構映射將按順序保留其基礎鍵。
先使用 create-struct 或 defstruct 建立結構基礎物件,然後使用 struct-map 或 struct 建立實例,即可建立 StructMaps。
(defstruct desilu :fred :ricky)
(def x (map (fn [n]
(struct-map desilu
:fred n
:ricky 2
:lucy 3
:ethel 4))
(range 100000)))
(def fred (accessor desilu :fred))
(reduce (fn [n y] (+ n (:fred y))) 0 x)
-> 4999950000
(reduce (fn [n y] (+ n (fred y))) 0 x)
-> 4999950000
StructMap 設定:create-struct defstruct accessor
建立個別結構:struct-map struct
在執行程式碼表單操作時,通常需要一個維護鍵順序的映射。陣列映射就是這樣的映射 - 它僅實作為鍵值鍵值… 的陣列。因此,它具有線性查詢效能,僅適用於非常小的映射。它實作完整的映射介面。可以使用 array-map 函數建立新的 ArrayMaps。請注意,僅在未「修改」時,陣列映射才會維護排序順序。後續的 assoc-ing 最終會導致它「變成」雜湊映射。
集合是唯一值集合。
對雜湊集合有文字支援
#{:a :b :c :d}
-> #{:d :a :b :c}
您可以使用 hash-set 和 sorted-set 函數建立集合
(hash-set :a :b :c :d)
-> #{:d :a :b :c}
(sorted-set :a :b :c :d)
-> #{:a :b :c :d}
您也可以使用 set 函數取得集合中值的集合
(set [1 2 3 2 1 2 3])
-> #{1 2 3}
集合是集合
(def s #{:a :b :c :d})
(conj s :e)
-> #{:d :a :b :e :c}
(count s)
-> 4
(seq s)
-> (:d :a :b :c)
(= (conj s :e) #{:a :b :c :d :e})
-> true
集合支援使用 disj 進行「移除」,以及 contains? 和 get,後者會傳回與鍵相等的集合中所包含的物件(如果找到的話)
(disj s :d)
-> #{:a :b :c}
(contains? s :b)
-> true
(get s :a)
-> :a
集合是其成員的函數,使用取得
(s :b)
-> :b
(s :k)
-> nil