定义原子?在 Clojure 中

问题描述 投票:0回答:4

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
4个回答
1
投票

一般来说,Clojure 并不像其他 Lisp 那样从根本上依赖于 cons 单元和原子。事实上,在 Clojure 中,您最终使用的向量和映射远远多于实际的列表(如果您忽略了实际编写 Clojure 代码的行为)。这就是 Clojure 中使用“原子”一词来指代 STM 概念的原因。传统的 Lisp 概念并没有那么有用。

因此,对

coll?
取负是 Lisp 原子的合理近似,但 Lisp 原子在 Clojure 中通常是一个外来概念。


1
投票

是的,所以事实证明

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)))))

0
投票

首先快速回答:

(def atomic? (complement coll?))
(map atomic? [0 "hi" [] {}]) => (true true false false)

但正如 @leetwinksi 和 @efraimmgon 观察到的,答案取决于你对原子的看法。例如,我们还可以将原子定义为 not-

seqable?
(即
(complement seqable?)
),这将进一步限制被视为原子的内容,因为包括字符串在内的许多类型都可以被视为序列。


0
投票
正如您所指出的,Clojure 中的

atom
完全不同。 首先我检查了类实例:

(defn atom? [x] (instance? clojure.lang.Atom x))

但这可能取决于实施细节。 相反,我现在使用 Clojure 界面:

(defn atom? [x] (instance? clojure.lang.IAtom x))

注意,cljs中有对应的协议:

cljs.core/IAtom

© www.soinside.com 2019 - 2024. All rights reserved.