簡體   English   中英

Clojure: cons (seq) vs. conj (list)

[英]Clojure: cons (seq) vs. conj (list)

我知道cons返回一個 seq 並且conj返回一個集合。 我也知道conj將項目“添加”到集合的最佳末尾,而cons總是將項目“添加”到前面。 這個例子說明了這兩點:

user=> (conj [1 2 3] 4) ; returns a collection
[1 2 3 4]
user=> (cons 4 [1 2 3]) ; returns a seq
(4 1 2 3)

對於向量、地圖和集合,這些差異對我來說很有意義。 但是,對於列表,它們似乎相同。

user=> (conj (list 3 2 1) 4) ; returns a list
(4 3 2 1)
user=> (cons 4 (list 3 2 1)) ; returns a seq
(4 3 2 1)

是否有使用列表的示例,其中conjcons表現出不同的行為,或者它們真的可以互換? 換種說法,是否有列表和 seq 不能等效使用的示例?

一個區別是conj接受任意數量的參數插入到集合中,而cons只接受一個:

(conj '(1 2 3) 4 5 6)
; => (6 5 4 1 2 3)

(cons 4 5 6 '(1 2 3))
; => IllegalArgumentException due to wrong arity

另一個區別在於返回值的類:

(class (conj '(1 2 3) 4))
; => clojure.lang.PersistentList

(class (cons 4 '(1 2 3))
; => clojure.lang.Cons

請注意,這些實際上不能互換; 特別是, clojure.lang.Cons沒有實現clojure.lang.Counted ,所以對它的count不再是一個常數時間操作(在這種情況下它可能會減少到 1 + 3 —— 1 來自線性遍歷第一個元素, 3 來自(next (cons 4 '(1 2 3))是一個PersistentList ,因此是Counted )。

我相信,名稱背后的意圖是cons意味着 cons(truct a seq) 1 ,而conj意味着 conj(oin an item into a collection)。 cons構造的seq以作為其第一個參數傳遞的元素開始,並將seq應用於第二個參數所產生的結果作為其next / rest部分; 如上所示,整個內容屬於clojure.lang.Cons類。 相反, conj總是返回與傳遞給它的集合大致相同類型的集合。 (粗略地說,因為PersistentArrayMap一旦超過 9 個條目就會變成PersistentHashMap 。)


1傳統上,在 Lisp 世界中, cons cons(tructs a pair),因此 Clojure 與 Lisp 傳統不同,它的cons函數構造了一個沒有傳統cdr的 seq。 cons的廣義用法意味着“構建某種類型或其他類型的記錄以將多個值保存在一起”目前在編程語言及其實現的研究中無處不在。 這就是提到“避免 consing”時的意思。

我的理解是你說的是真的:列表上的 conj 相當於列表上的 cons。

您可以將 conj 視為“在某處插入”操作,而將 cons 視為“在頭部插入”操作。 在列表中,最合乎邏輯的是插入到頭部,所以在這種情況下 conj 和 cons 是等價的。

另一個區別是,因為conj將序列作為第一個參數,所以在更新某個序列的ref時,它可以很好地與alter配合使用:

(dosync (alter a-sequence-ref conj an-item))

這基本上以線程安全的方式執行(conj a-sequence-ref an-item) 這不適用於cons 有關更多信息,請參閱 Stu Halloway編寫的編程 Clojure 中的並發一章。

另一個區別是列表的行為?

(list? (conj () 1)) ;=> true
(list? (cons 1 ())) ; => false

Tupelo 庫中專門的函數可以向任何順序集合添加附加值或前置值:

(append [1 2] 3  )   ;=> [1 2 3  ]
(append [1 2] 3 4)   ;=> [1 2 3 4]

(prepend   3 [2 1])  ;=> [  3 2 1]
(prepend 4 3 [2 1])  ;=> [4 3 2 1]

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM