我正在写一个clojure递归函数,所以给出:
(luty [1 2 3 4])
应该有这样的输出:
((1 2 3 4) (2 3 4) (3 4) (4) ()
我的代码是:
(defn luty [a1]
(if (empty? a1)
(list )
(cons (seq a1) (luty (rest a1) )
)))
我得到了输出:
((1 2 3 4) (2 3 4) (3 4) (4)) //comment missing a ()
有人可以告诉我哪里出错了吗?
答案 0 :(得分:2)
如果我们打印出这个过程并查看倒数第二个操作:
user> (defn luty [a1]
(println "a1 is" a1)
(if (empty? a1)
()
(cons (seq a1) (luty (rest a1)))))
#'user/luty
user> (luty [1 2 3 4])
a1 is [1 2 3 4]
a1 is (2 3 4)
a1 is (3 4)
a1 is (4)
a1 is ()
((1 2 3 4) (2 3 4) (3 4) (4))
user> (cons '(4) ())
((4))
我们可以看到,将(4)
添加到空列表的结果为((4))
,而不是((4) ())
,这是您最想要的。这可以通过使基本案例成为包含空列表的列表而不仅仅是空列表
user> (defn luty [a1]
(if (empty? a1)
'(())
(cons (seq a1) (luty (rest a1)))))
#'user/luty
user> (luty [1 2 3 4])
((1 2 3 4) (2 3 4) (3 4) (4) ())
答案 1 :(得分:1)
cons的返回值是一个列表,第一个参数作为第一个元素,列表的其余部分作为第二个参数。如果第二个参数为空或nil,则表示您获得一个列表,其中第一个参数为单个成员。
这样做的原因是列表(概念上,至少在clojure中)具有2空格单元的链表; head元素的一个指针和尾部的一个指针(另一个列表,在clojure中保证是类似seq的东西 - 在许多其他lisps中你可以将第二个指针设置为你想要的任何值,所以你不是保证从那里得到一个“正确”的列表)。 “tail”位置的nil标志着列表的结尾。
列表是最容易实现且易于理解的持久性(在不可变的,结构共享的clojure意义上)数据结构。
答案 2 :(得分:1)
只是为了给你一个不同的方式来看待它:
user> (defn luty [a1]
(reductions (fn [c _] (rest c)) (or (seq a1) '()) (-> a1 count range)))
=> #'user/luty
user> (luty [1 2 3 4])
=> ((1 2 3 4) (2 3 4) (3 4) (4) ())
user> (luty [])
=> (())
user> (luty nil)
=> (())