定义原子?在clojure

时间:2016-06-16 21:51:48

标签: clojure

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

这是对的吗?

4 个答案:

答案 0 :(得分:1)

总的来说,Clojure并不像其他Lisp那样从根本上依赖于cons细胞和原子。事实上,你经常最终使用向量和映射远远超过Clojure中的实际列表(如果你省略了实际编写Clojure代码的行为)。这就是为什么单词“atom”用于指代Clojure中的STM概念。传统的Lisp概念并没有那么有用。

所以你对sudo apt-get install php5-mysqli 的否定是Lisp原子的合理近似,但Lisp原子在Clojure中通常是一个外来概念。

答案 1 :(得分:1)

是的,事实证明coll?不是Clojure等同于Common Lisp consp。 原因是空列表()coll,所以我得到了堆栈溢出。 正确的答案是检查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)))))

答案 2 :(得分:0)

(def atomic? (complement coll?))

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

编辑:正如@leetwinksi指出的那样,此实现不适用于所有可选值,例如int-array
在clojure中,它们是几种类型的聚合抽象(事物的集合)。基于seqable值的解决方案是:

(def atomic? (complement seq?))

(map atomic? [0 "hi" [] '()]) => (true true true false)

complement接受谓词函数并返回相反的谓词函数。它可以实现为:

(defn my-complement [pred-fun] #(not pred-fun %))

所以这实际上取决于你想要如何定义 atom

我很高兴你问,因为我最近想要相同的功能: - )

答案 3 :(得分:0)

正如你所指出的,Clojure中的{p> atom完全不同。 起初我检查了类实例:

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

然而,这可能依赖于实施细节。 相反,我现在使用Clojure接口:

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

请注意,cljs中有相应的协议:cljs.core/IAtom