我正在编写一个程序,它使用经典的cons对和Common Lisp,Scheme等等。
(deftype Cons [car cdr]
clojure.lang.ISeq
(first [c] (.car c))
(more [c] (.cdr c))
我通过链接cons单元创建列表,例如(Cons. a (Cons. b nil))
列表包含a
和b
。我编写了一个将Clojure集合转换为缺点列表的函数:
(defn conslist [xs]
(if (empty? xs)
nil
(Cons. (first xs) (conslist (rest xs)))))
这可行但如果xs
太大则会溢出。 recur
不起作用,因为递归调用不在尾部位置。将loop
与累加器一起使用是行不通的,因为cons
只会将内容放在前面,当每个递归器为您提供 next 项时,我无法使用{ {1}}。
我该怎么办?
编辑:最后,事实证明,如果你使用它,Clojure从根本上不是为了支持cons对(你不能将尾部设置为非seq)。我最终只是创建了一个自定义数据结构和car / cdr函数。
答案 0 :(得分:2)
(defn conslist [xs]
(loop [xs (reverse xs) res nil]
(if (empty? xs)
res
(recur (rest xs) (Cons. (first xs) res)))))
答案 1 :(得分:0)
lazy-seq
是你的朋友。它需要一个评估为ISeq的主体,但在调用lazy-seq
的结果之前不会对主体进行求值。
(defn conslist [xs]
(if (empty? xs)
nil
(lazy-seq (Cons. (first xs) (conslist (rest xs))))))