递归函数的lazy-seq

发布于 2024-10-23 21:45:14 字数 390 浏览 5 评论 0原文

抱歉,标题含糊不清,我想我只是不太了解我的问题,还无法提出这个问题,但就这样吧。我想编写一个递归函数,它需要一系列函数来评估,然后用它们的结果和结果调用自身。很快。递归在某个返回数字的函数处停止。

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

我想我正在要求一个惰性序列。这是一根管道,一端充满了函数的评估,另一端则输出历史结果。

Sorry for the vague title, I guess I just don't understand my problem well enough to ask it yet but here goes. I want to write a recursive function which takes a sequence of functions to evaluate and then calls itself with their results & so on. The recursion stops at some function which returns a number.

However, I would like the function being evaluated at any point in the recursion, f, to be wrapped in a function, s, which returns an initial value (say 0, or the result of another function i) the first time it is evaluated, followed by the result of evaluating f (so that the next time it is evaluated it returns the previously evaluated result, and computes the next value). The aim is to decouple the recursion so that it can proceed without causing this.

I think I'm asking for a lazy-seq. It's a pipe that's filling-up with evaluations of a function at one end, and historical results are coming out of the other.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

满地尘埃落定 2024-10-30 21:45:14

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

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

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

如果您需要为此构建一个测试(检查值),则可以使用函数中的 if 轻松完成(尽管它不会停止遍历 seq)。如果你想在条件为真时提前退出,那么你需要编写自己的循环/递归,amalloy 已经做得很好了。

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

Your description reminds me some of reductions? Reductions will perform a reduce and return all the intermediate results.

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

Here (range 10) creates a seq of 0 to 9. Reductions applies + repeatedly, passing the previous result of + and the next item in the sequence. All of the intermediate results are returned. You might find it instructive to look at the source of reductions.

If you need to build a test (check for value) into this, that's easy to do with an if in your function (although it won't stop traversing the seq). If you want early exit on a condition being true, then you'll need to write your own loop/recur which amalloy has already done well.

I hate to say it, but I suspect this might also be a case for the State Monad but IANAMG (I Am Not A Monad Guy).

戈亓 2024-10-30 21:45:14

我不明白你的整个目标:你使用的很多术语都很模糊。比如,你想要评估一系列函数然后重复它们的结果是什么意思?这些函数必须是无参数函数(thunks),那么,我想呢?但是有一个 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

I don't understand your entire goal: a lot of the terms you use are vague. Like, what do you mean you want to evaluate a sequence of functions and then recur on their results? These functions must be no-arg functions (thunks), then, I suppose? But having a thunk which first returns x, and then returns y the next time you call it, is pretty vile and stateful. Perhaps trampoline will solve part of your problem?

You also linked to something you want to avoid, but seem to have pasted the wrong link - it's just a link back to this page. If what you want to avoid is stack overflow, then trampoline is likely to be an okay way to go about it, although it should be possible with just loop/recur. This notion of thunks returning x unless they return y is madness, if avoiding stack overflow is your primary goal. Do not do that.

I've gone ahead and taken a guess at the most plausible end goal you might have, and here's my implementation:

(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
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文