在conj
中,原始集合是第一个参数,在cons
中,它是第二个参数。
我是clojure的新手,这看起来有点令人困惑。这两个函数有类似的行为,但为什么参数顺序不同,它是故意设计的吗?
(conj '(1 2 3) 4)
; => (4 1 2 3)
(cons 4 '(1 2 3))
; => (4 1 2 3)
我知道这两个函数不同,但为什么conj
和cons
将原始集合放在不同的参数顺序中。
答案 0 :(得分:5)
cons
传统上意味着构造新对象,将第一个arg置于第二个arg,以及args是如何排序的。
以下是LISP cons的引用,
在LISP术语中,表达“将x缩写为y”意味着构造一个
的新对象loc
但是(cons x y)
通常是附加给定的数据结构,但取决于你使用的clojure数据类型。这就是为什么集合首先出现然后要追加的元素。
让我们看看conjoin
;
Vector
但对于user=> (type [3 5 7 11])
clojure.lang.PersistentVector
user=> (cons 1 [3 5 7 11])
(1 3 5 7 11)
user=> (conj [3 5 7 11] 13)
[3 5 7 11 13]
,List
也可以预先添加
conjoin
doc for conj
也描述了这一点。
user=> (type '(3 5 7 11))
clojure.lang.PersistentList
user=> (cons 1 '(3 5 7 11))
(1 3 5 7 11)
user=> (conj '(3 5 7 11) 13)
(13 3 5 7 11)
据我所知,该命令适用于任何其他功能语言。这是scala;
user=> (doc conj)
-------------------------
clojure.core/conj
([coll x] [coll x & xs])
conj[oin]. Returns a new collection with the xs
'added'. (conj nil item) returns (item). The 'addition' may
happen at different 'places' depending on the concrete type.
nil
答案 1 :(得分:1)
另一个答案给出了一个很好的概述。我还想指出conj
和cons
:
(cons 1 [2 3]) => <#clojure.lang.Cons (1 2 3)>
(conj [2 3] 9) => <#clojure.lang.PersistentVector [2 3 9]>
(cons 1 (quote (2 3))) => <#clojure.lang.Cons (1 2 3)>
(conj (quote (2 3)) 9) => <#clojure.lang.PersistentList (9 2 3)>
类型clojure.lang.Cons
是一种与clojure.lang.PersistentList
类似(但不完全相同)的顺序类型:
(supers clojure.lang.Cons) =>
#{ clojure.lang.ASeq
clojure.lang.IHashEq
clojure.lang.IMeta
clojure.lang.IObj
clojure.lang.IPersistentCollection
clojure.lang.ISeq
clojure.lang.Obj
clojure.lang.Seqable
clojure.lang.Sequential
java.io.Serializable
java.lang.Iterable
java.lang.Object
java.util.Collection
java.util.List }
为了简化添加到序列的开头或结尾,you may be interested in the functions append
and prepend
.
答案 2 :(得分:-1)
简而言之,因为他们相反。在cons中,目标元素是第一个,并且集合成为结果序列的其余部分。另外,目标元素成为最终集合的尾部。
我可能会建议您阅读SICP的第一章,其中描述了cons和consing
术语。