从长期运行的递归Clojure函数进行进度更新

从长期运行的递归Clojure函数进行进度更新,clojure,callback,watch,Clojure,Callback,Watch,我编写了这个助手函数: (定义迭代收敛) 返回调用(f x)若干次的值,直到 `x`更改小于公差,`tol`。将不会执行更多更改 比“b”(例如救助)倍还多。” [f][b] (循环[f x x0 tol b b i 0] (如果(>=IB) (抛出(ex info“未能收敛” {:类型::未能收敛:tol:b}) (让[x'(f x)] (如果(

我编写了这个助手函数:

(定义迭代收敛)
返回调用(f x)若干次的值,直到
`x`更改小于公差,`tol`。将不会执行更多更改
比“b”(例如救助)倍还多。”
[f][b]
(循环[f x x0 tol b b i 0]
(如果(>=IB)
(抛出(ex info“未能收敛”
{:类型::未能收敛:tol:b})
(让[x'(f x)]
(如果(<(abs(-x'))tol)
x'
(重复f x’tol b(公司i()()())))
根据参数,这可能需要大量时间。我想要一份关于进展情况的功能报告。我不希望它绑定到控制台输出(例如,
println

我目前的想法:

  • 添加回调函数作为参数。每次通过都要打电话。这允许推送通知
  • 添加一个原子作为参数。为每个传递更新它。这将允许使用轮询或推送通知
  • 添加core.async通道作为参数。与上述(1)类似,但可能提供更好的多核性能

  • 你会做什么?为什么?

    我个人会将这些选项按相反的顺序排列,#3是最灵活的,因为这样你就可以以更有趣(和有趣)的方式处理输出


    如果您正在寻找更多选项,我可以推荐使用作为准确生成长时间运行流程的定期报告的一种方法。

    只需让它返回候选答案的惰性序列即可。然后你可以在闲暇时反复阅读它们,在回答可以接受时停止,或者当你决定花费太长时间而想放弃时停止。

    我喜欢你所说的精神——因为(a)这是一个很好的建议,而(b)这不是我所期望的。也就是说,我认为它不符合上述职能的目标和职责。例如,我用它来做泰勒展开。根据设计,调用方不应该决定是否继续。这就是
    迭代收敛
    的作用。调用方需要的是一个“状态更新”,因此它会返回一个延迟的状态更新序列,每个更新都包含一些采取有意义的操作的方法。不需要任何“带外”通信,这将更难管理。一个不关心更新的调用方只需调用更新序列上的
    last
    ,就可以得到最终答案;感兴趣的调用者一次一个地进行更新并执行任何操作。或者,您可以将解决方案分为两种方法—一种新方法,生成@amalloy描述的惰性seq,然后更改此方法以执行副作用通知并返回
    last
    。作为一个好处,这个包装函数可以负责决定结果何时“足够好”,并使内部函数无限重复。