4clojure #57 - 简单递归
4clojure #57 - Simple Recursion
我正在经历 4 个 clojure 问题,我不明白为什么 following code is working
user=> ((fn foo [x] (when (> x 0) (conj (foo (dec x)) x))) 5)
(5 4 3 2 1)
我知道 (foo (dec x))
必须被视为 PersistentCollection 才能正常工作,但那里发生的事情是个谜。任何了解它为什么工作以及为什么按此顺序工作的任何见解都将不胜感激。
我们来分解一下:
(foo 5) ;;=>
(conj (foo 4) 5) ;;=>
(conj (conj (foo 3) 4) 5) ;;=>
...
(conj (conj (conj (conj (conj nil 1) 2) 3) 4) 5)
;; (conj nil 1) == '(1), so:
;;=>
(conj (conj (conj (conj '(1) 2) 3) 4) 5)
;; conj-ing adds to the head of the list
;;=>
(conj (conj (conj '(2 1) 3) 4) 5)
;;=>
(conj (conj '(3 2 1) 4) 5)
...
;;=> '(5 4 3 2 1)
让我们仔细看看您的代码示例。基本上,它只是一个具有以下 foo
函数的函数调用 (foo 5)
:
(defn foo [x]
(when (> x 0)
(conj (foo (dec x)) x)))
当您使用 x
的任何非正值调用 foo
时,它 returns nil
。否则它 return conj
加入 x
到调用 (foo (dec x))
.
的结果
因此,调用 (foo 2)
大致相当于以下代码:
(conj (conj nil 1) 2)
可能会让您感到困惑的是 conj
行为,其中 nil
值作为第一个参数传递。
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.
另一件可能让您感到困惑的事情是结果列表中元素的顺序。 conj
旨在以最有效的方式向 PersistentCollection
添加新元素。在列表的情况下 conj
将新元素添加到原始列表的开头:
=> (conj '(1) 2)
(2 1)
我正在经历 4 个 clojure 问题,我不明白为什么 following code is working
user=> ((fn foo [x] (when (> x 0) (conj (foo (dec x)) x))) 5)
(5 4 3 2 1)
我知道 (foo (dec x))
必须被视为 PersistentCollection 才能正常工作,但那里发生的事情是个谜。任何了解它为什么工作以及为什么按此顺序工作的任何见解都将不胜感激。
我们来分解一下:
(foo 5) ;;=>
(conj (foo 4) 5) ;;=>
(conj (conj (foo 3) 4) 5) ;;=>
...
(conj (conj (conj (conj (conj nil 1) 2) 3) 4) 5)
;; (conj nil 1) == '(1), so:
;;=>
(conj (conj (conj (conj '(1) 2) 3) 4) 5)
;; conj-ing adds to the head of the list
;;=>
(conj (conj (conj '(2 1) 3) 4) 5)
;;=>
(conj (conj '(3 2 1) 4) 5)
...
;;=> '(5 4 3 2 1)
让我们仔细看看您的代码示例。基本上,它只是一个具有以下 foo
函数的函数调用 (foo 5)
:
(defn foo [x]
(when (> x 0)
(conj (foo (dec x)) x)))
当您使用 x
的任何非正值调用 foo
时,它 returns nil
。否则它 return conj
加入 x
到调用 (foo (dec x))
.
因此,调用 (foo 2)
大致相当于以下代码:
(conj (conj nil 1) 2)
可能会让您感到困惑的是 conj
行为,其中 nil
值作为第一个参数传递。
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.
另一件可能让您感到困惑的事情是结果列表中元素的顺序。 conj
旨在以最有效的方式向 PersistentCollection
添加新元素。在列表的情况下 conj
将新元素添加到原始列表的开头:
=> (conj '(1) 2)
(2 1)