Common Lisp 有一个
atom
谓词,但 Clojure 似乎没有等价的 - Clojure 中的原子是完全不同的东西。
在 ANSI Common Lisp 中,Paul Graham 将其定义为
(not (consp x))
。
(not (coll? x))
是正确的实施吗?
我还不太习惯集合抽象。
编辑:
我需要这个谓词来让函数复制树,例如:
(defn our-copy-tree
[tr]
(if-not (coll? tr)
tr
(cons (our-copy-tree (first tr))
(our-copy-tree (rest tr)))))
这样对吗?
一般来说,Clojure 并不像其他 Lisp 那样从根本上依赖于 cons 单元和原子。事实上,在 Clojure 中,您最终使用的向量和映射远远多于实际的列表(如果您忽略了实际编写 Clojure 代码的行为)。这就是 Clojure 中使用“原子”一词来指代 STM 概念的原因。传统的 Lisp 概念并没有那么有用。
因此,对
coll?
取负是 Lisp 原子的合理近似,但 Lisp 原子在 Clojure 中通常是一个外来概念。
是的,所以事实证明
coll?
不会是与 Common Lisp consp
等价的 Clojure。
原因是空列表
()
是一个coll
,所以我在使用CL(consp '()); => false)
时出现了堆栈溢出。
正确的答案也是检查 tr 是否为空,因此:
(defn our-copy-tree
[tr]
(if (or (not (coll? tr)) (empty? tr))
tr
(cons (our-copy-tree (first tr))
(our-copy-tree (rest tr)))))
首先快速回答:
(def atomic? (complement coll?))
(map atomic? [0 "hi" [] {}]) => (true true false false)
但正如 @leetwinksi 和 @efraimmgon 观察到的,答案取决于你对原子的看法。例如,我们还可以将原子定义为 not-
seqable?
(即 (complement seqable?)
),这将进一步限制被视为原子的内容,因为包括字符串在内的许多类型都可以被视为序列。
atom
完全不同。
首先我检查了类实例:
(defn atom? [x] (instance? clojure.lang.Atom x))
但这可能取决于实施细节。 相反,我现在使用 Clojure 界面:
(defn atom? [x] (instance? clojure.lang.IAtom x))
注意,cljs中有对应的协议:
cljs.core/IAtom