【发布时间】:2015-12-23 00:16:18
【问题描述】:
我是 Clojure 的新手,我以前在其他语言中看到过这种模式。我想我确实知道递归是如何工作的,但我不知道如何阅读和思考如何编写这样的代码。这是一个简单的例子:
(defn remove-dups [str]
(when-let [[fst & rst] (seq str)]
(if (= fst (first rst))
(remove-dups rst)
(cons fst (remove-dups rst)))))
我敢肯定,对于经验丰富的 Clojurist 来说,这看起来并不难。但是,我仍然不知道如何阅读这样的代码。也许有一种模式你必须学会理解?他们说 Lisp 和 Clojure 是“从内到外”读取的,但我找不到一种快速的方法来解析这样的代码。也许有一种方法可以通过打印步骤来“解开”递归模式?请有人教我以分而治之的方式思考。
【问题讨论】:
-
旁白:这不是好的代码,因为它会消耗堆栈,如果需要太多递归步骤就会崩溃。如果
loop/recur和trampoline不能使用(并且循环/递归不能在这里使用,因为它不在尾部位置),一个不同的构造,即。for,合适。 -
@CharlesDuffy 我听到了。对不起,我找不到更好的例子。如果我能写出更好的 Clojure 代码,我一开始就不会问这个问题。我认为虽然这段代码完美地说明了我的斗争,但斗争是真实的;[
-
我听到了;不幸的是,我没有什么好的建议。我自己的方法包括长时间的重复曝光,直到点击成功,但这并不意味着我知道如何让其他人更轻松地完成这个过程。虽然,是的,一个人可以“解开”东西,但是虽然我可以用白板教它,但用文字并不容易。也许讨论在迭代算法和递归算法之间转换的过程会起作用,但简单的算法只适用于 TCO 的相同场景,而且这个例子不是其中之一。
-
阅读this。更好的例子会有所帮助。
-
另一边:通常你可以组合库函数,而不是直接
cons将列表递归地组合在一起。这个例子变成了(->> str (partition-by identity) (map first))。