对于模糊的标题感到抱歉,我想我只是不明白我的问题还不能问它但是这里有。我想写一个递归函数,它需要一系列函数来评估,然后用它们的结果调用自己。等等。递归在某个返回数字的函数处停止。
但是,我希望在递归中的任何一点评估的函数f被包装在一个函数s中,它在第一次返回一个初始值(比如0,或者是另一个函数i的结果)它被评估,然后是评估f的结果(这样下一次评估时它会返回先前评估的结果,并计算下一个值)。目的是解耦递归,以便它可以继续而不会导致this。
我想我要求一个懒惰的seq。这是一个充满了一端功能评估的管道,历史结果正在另一端。
答案 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