Clojure

序列

Clojure 定義許多演算法以序列 (seq) 的形式表示。Seq 是一個邏輯清單,與大多數 Lisp 使用具體的 2 槽位結構來表示清單不同,Clojure 使用 ISeq 介面允許許多資料結構以序列的形式提供對其元素的存取。 seq 函式會產生一個適於該集合的 ISeq 實作。Seq 與反覆運算器不同,在於它們是持續且不可變的,而不是集合中的狀態游標。因此,它們的用途遠超過 foreach - 函式可以消耗和產生 seq,它們是執行緒安全的,它們可以共用結構等。

序列函式庫函式大多是延遲的,也就是說,傳回 seq 的函式會在消耗時逐步執行,因此也會逐步消耗任何 seq 引數。傳回延遲 seq 的函式可以使用 lazy-seq 巨集來實作。另請參閱 lazy

seq 用於實作 Iterable 的物件時,產生的序列仍然是不變且持續的,並且會表示跨越資料的一次傳遞。由於該傳遞可能是延遲發生的,因此傳遞可能會看到在呼叫 seq 之後發生的變更。此外,如果後援反覆運算器會受到 ConcurrentModificationException 影響,則產生的 seq 也是如此。當 seq 用於原生 Java 陣列時,基礎陣列的變更會反映在 seq 中 - 您必須複製來源陣列才能獲得完全的不變性。話雖如此,在 Iterables 和陣列上使用 seq 仍然有很多用處,因為 seq 支援多重傳遞和延遲演算法。穩健的程式不應變異具有 seq 的陣列或 Iterables。

seq 函式庫中的許多函式會採用一個或多個集合,對它們呼叫 seq,然後對產生的 seq 進行操作。換句話說,這些函式中的許多會採用集合,但對其 seq 進行操作。

Seq 介面

(first coll)

傳回集合中的第一個項目。對其引數呼叫 seq。如果 coll 為 nil,則傳回 nil。

(rest coll)

傳回第一個項目之後的項目序列。對其引數呼叫 seq。如果沒有更多項目,則傳回邏輯序列,其中 seq 傳回 nil。

(cons item seq)

傳回新的 seq,其中 item 為第一個元素,seq 為其餘部分。

有關 restnextlazy-seq 的討論,請參閱 lazy

Seq 函式庫

以下是主要序列函式的範例,依其功能大致分組。有些函式可以用不同的方式使用,因此會出現在多個群組中。在 API 區段中列出了更多函式。

自 Clojure 1.7 起,Clojure 也提供了 transducers,一種在集合上進行可組合轉換的替代模型。Transducers 將轉換的輸入、處理和輸出部分解耦,並允許在更多情境中重複使用轉換,例如 core.async 通道。如果省略輸入集合,下方清單中的許多序列函數將建立 transducers。請參閱 Transducers 頁面以取得更多詳細資料。

序列輸入,序列輸出

由較長序列產生較短序列:distinct filter remove for keep keep-indexed
由較短序列產生較長序列:cons concat lazy-cat mapcat cycle interleave interpose
缺少頭部項目的序列:rest next fnext nnext drop drop-while nthnext for
缺少尾部項目的序列:take take-nth take-while butlast drop-last for
序列重新排列:flatten reverse sort sort-by shuffle
建立巢狀序列:split-at split-with partition partition-all partition-by
處理序列的每個項目以建立新的序列:map pmap mapcat for replace reductions map-indexed seque

使用序列

從序列中擷取特定編號的項目:first ffirst nfirst second nth when-first last rand-nth
從序列建立集合:zipmap into reduce set vec into-array to-array-2d frequencies group-by
將序列的項目作為引數傳遞給函數:apply
從序列計算布林值: not-empty some reduce seq? every? not-every? not-any? empty?
使用謂詞搜尋序列: some filter
強制評估延遲序列: doseq dorun doall
檢查延遲序列是否已強制評估: realized?

建立序列

從集合建立延遲序列: seq vals keys rseq subseq rsubseq
從產生函數建立延遲序列: lazy-seq repeatedly iterate
從常數建立延遲序列: repeat range
從其他物件建立延遲序列: line-seq resultset-seq re-seq tree-seq file-seq xml-seq iterator-seq enumeration-seq