我的猜测是,你正在使用向量作为序列。
(eliminate 3 [3 3])
;()
(eliminate 3 [3 [3]])
;([3])
这本来是小事找到了你向我们展示一个例子:啧!
这是怎么回事?
虽然载体seqable,他们不是序列:
(seq? [])
;false
在外部级,你把lst
作序,所以first
和rest
工作,因为他们包装他们的论点的隐含seq
。但是seq?
将在任何立即封闭的矢量上失败,并且甚至不会看到那些矢量。
如果您将seq?
替换为sequential?
,则列表和向量将起作用。
(sequential? [])
;true
更为严重,因为@noisesmith指出的,是你在内部范围的def
和defn
使用。将它们替换为let
或letfn
。
你也可以提高你的风格:
- 更换
(if-not (empty? lst) ...)
与(if (seq lst) ...)
。
- 使用
cond
来扁平化嵌套if
s。这需要反转 (1)中的测试,因此不需要它。
- 使用
recur
为尾递归的情况下,你发现value
,因为 @Mark呢。
如果你不希望看到的结果,现在看起来远:
(defn eliminate [value lst]
(letfn [(sub-eliminate [lst]
(let [current-item (first lst)]
(cond
(empty? lst) '()
(sequential? current-item) (cons (sub-eliminate current-item)
(sub-eliminate (rest lst)))
(= value current-item) (recur (rest lst))
:else (cons current-item (sub-eliminate (rest lst))))))]
(sub-eliminate lst)))
有剩余的痛处:
- 你调用
(first lst)
你知道lst
是前不是空的。没有 造成伤害:你只会得到nil
,你忽略了。
使用解构
一种替代Apporach可以经常使用destructuring缩略序列的递归处理。我倾向于这样来表达你的函数:
(defn eliminate [x xs]
((fn rem-x [xs]
(if-let [[y & ys] (seq xs)]
(if (= x y)
(recur ys)
(cons
(if (sequential? y) (rem-x y) y)
(rem-x ys)))
()))
xs))
时,如果未能在什么输入?我试了几次,但我没有看到它失败。请在你的问题中包括一个例子。 – 2014-10-03 10:29:19
将右括号放在一行上是[认为不好的样式](https://github.com/bbatsov/clojure-style-guide#gather-trailing-parens)(所有LISP都一样) – Sylwester 2014-10-03 13:01:49
'def'和' defn'只能创建全局变量,使用'let' /'fn' /'letfn'作为本地绑定,'atom' /'ref' /'agent'用于全局变量状态为 – noisesmith 2014-10-03 13:20:20