lazy-seq用于递归函数

时间:2011-03-18 07:09:19

标签: recursion clojure sequence lazy-evaluation

对于模糊的标题感到抱歉,我想我只是不明白我的问题还不能问它但是这里有。我想写一个递归函数,它需要一系列函数来评估,然后用它们的结果调用自己。等等。递归在某个返回数字的函数处停止。

但是,我希望在递归中的任何一点评估的函数f被包装在一个函数s中,它在第一次返回一个初始值(比如0,或者是另一个函数i的结果)它被评估,然后是评估f的结果(这样下一次评估时它会返回先前评估的结果,并计算下一个值)。目的是解耦递归,以便它可以继续而不会导致this

我想我要求一个懒惰的seq。这是一个充满了一端功能评估的管道,历史结果正在另一端。

2 个答案:

答案 0 :(得分:3)

您的描述让我想起了reductions的一些内容?减少将执行减少并返回所有中间结果。

user> (reductions + (range 10))
(0 1 3 6 10 15 21 28 36 45)

这里(范围10)创建一个0到9的seq。减少重复应用+,传递+的前一个结果和序列中的下一个项目。返回所有中间结果。您可能会发现查看减少的source是有益的。

如果你需要在其中构建一个测试(检查值),那么在你的函数中使用if很容易(尽管它不会停止遍历seq)。如果你想在条件为真的情况下提前退出,那么你需要编写自己的循环/重复,而合金已经做得很好。

我不想这么说,但我怀疑这可能也是国家Monad的情况,但IANAMG(我不是Monad Guy)。

答案 1 :(得分:0)

我不明白你的整个目标:你使用的很多术语含糊不清。比如,你想要评估一系列函数然后重复他们的结果是什么意思?这些函数必须是无参数函数(thunk),那么,我想?但是有一个thunk首先返回x,然后在你下次调用它时返回y,这是非常卑鄙和有状态的。也许trampoline会解决部分问题吗?

您还链接到了您想要避免的内容,但似乎粘贴了错误的链接 - 它只是返回此页面的链接。如果你想要避免的是堆栈溢出,那么蹦床很可能是一个可行的方法,尽管它应该可以只用loop / recur。除非他们返回y,否则返回x的thunks的概念是 madness ,如果避免堆栈溢出是你的主要目标。不要那样做。

我已经开始对你可能拥有的最合理的最终目标进行猜测,这是我的实现:

(defn call-until-number [& fs]
  (let [numeric (fn [x] (when (number? x) x))]
    (loop [fs fs]
      (let [result (map #(%) fs)]
        (or (some numeric result)
            (recur result))))))

(call-until-number (fn [] (fn [] 1))) ; yields 1
(call-until-number (fn [] (fn [] 1))  ; yields 2
                   (fn [] 2))
(call-until-number (fn f [] f)) ; never returns, no overflow