我的猜測是,你正在使用向量作爲序列。
(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