2011-03-18 67 views
2

对不起,模糊的标题,我想我只是不明白我的问题,足以问问它,但在这里。我想写一个递归函数,它需要一系列函数来评估,然后用他们的结果&等等来调用它自己。递归在某个返回数字的函数处停止。lazy-seq为递归函数

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

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

回答

0

我不明白你的整个目标:你使用的很多术语都是模糊的。就像,你想要评估一系列函数然后重复他们的结果是什么意思?这些函数必须是无参数函数(thunk),那么,我想呢?但有一个thunk首先返回x,然后在你下次调用它时返回y,这是相当邪恶和有状态的。也许trampoline将解决你的问题的一部分?

你也链接到你想避免的东西,但似乎粘贴了错误的链接 - 它只是一个链接回到这个页面。如果你想避免堆栈溢出,那么蹦床很可能是一个好方法,尽管循环/重复应该是可能的。除非返回y,否则thunk返回x的这个概念是疯狂,如果避免堆栈溢出是您的主要目标。不要那样做。

我已经先行一步,在你可能有最合理的最终目标迈出了猜测,这是我的实现:

(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 
+0

谢谢你们,看起来像蹦床可能是我需要的东西 – gone 2011-03-21 05:58:01

3

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

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

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

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

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