4clojure#57 - 简单递归

1 recursion clojure

我正在经历4clojure问题,我无法理解为什么以下代码工作

user=> ((fn foo [x] (when (> x 0) (conj (foo (dec x)) x))) 5)
(5 4 3 2 1)
Run Code Online (Sandbox Code Playgroud)

我知道(foo (dec x))必须将其视为PersistentCollection才能使其工作,但正在发生的事情是个谜.任何洞察它为什么工作,以及为什么在这个顺序将不胜感激.

Leo*_*tny 6

让我们仔细看看您的代码示例.基本上,它只是一个(foo 5)具有以下foo功能的函数调用:

(defn foo [x]
  (when (> x 0)
    (conj (foo (dec x)) x)))
Run Code Online (Sandbox Code Playgroud)

当你foo用任何非正值调用x它时返回nil.否则它conj会将x调用结果返回给调用结果(foo (dec x)).

因此,调用(foo 2)大致相当于以下代码:

(conj (conj nil 1) 2)
Run Code Online (Sandbox Code Playgroud)

可能会让您感到困惑的是conjnil值作为第一个参数传递的行为.

conj威胁nil作为空列表(),因此(conj nil 1)产生相同的结果(conj () 1).此行为记录在conj文档中:

=> (doc conj)
(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.
Run Code Online (Sandbox Code Playgroud)

另一件可能让您感到困惑的事情是结果列表中元素的顺序.conj旨在以PersistentCollection最有效的方式添加新元素.如果列表conj 将新元素添加到原始列表的开头:

=> (conj '(1) 2)
(2 1)
Run Code Online (Sandbox Code Playgroud)