【发布时间】:2019-12-24 04:14:04
【问题描述】:
我是Clojure的新手,问题源于我曾经查看conj的源代码:
(def conj
(fn ^:static conj
([] [])
([coll] coll)
([coll x] (clojure.lang.RT/conj coll x));4
([coll x & xs] ;1
(if xs ;2
(recur (clojure.lang.RT/conj coll x) (first xs) (next xs)) ;3
(clojure.lang.RT/conj coll x)))))
conj的源码显示它使用recur来实现该功能。这个源代码看起来很简单。
我感到困惑的是它在确定递归是否需要继续时使用的条件。看起来它检查变量参数是否为nil,但如果变量参数为nil,它很快就相当于conj 的第三个“arity”?
然后我尝试评估以下表达式:
user=> (conj [] 1 (next []))
[1 nil]
user=>
它工作正常并成功地将nil添加到向量中。我知道clojure实际上将nil包装在一个列表中并将其传递给函数,但我不明白为什么recur可以传递一个真正的nil?为什么clojure会识别并匹配正确的“arity”?
user=> (def my_conj
(fn [coll x & xs]
(println "xs is" xs)
(if xs
(recur (clojure.lang.RT/conj coll x) (first xs) (next xs))
(clojure.lang.RT/conj coll x))))
#'user/my_conj
user=> (my_conj [] 1 (next []))
xs is (nil)
xs is nil
[1 nil]
【问题讨论】:
标签: clojure clojure-java-interop clojure-core.logic