【问题标题】:Clojure: Bailing out of a functionClojure:退出函数
【发布时间】:2018-03-21 16:22:13
【问题描述】:

我正在为 Clojure 编写一个简单的测试数据生成系统,它为给定函数生成一个控制流图并对输入数据执行进化搜索。驱动这种进化搜索的适应度函数是目标函数的一个版本,每个条件形式的每个分支都有标签(例如(if TEST (do (branch-label ...) THEN) (do (branch-label ...) ELSE)。 branch-label 函数使用控制流图中节点的索引调用,该索引对应于函数执行的当前点和另一个分支的分支距离。然后该函数根据接近水平和分支距离计算适应度值并将其存储在原子中。为了加快处理速度,我希望适应度函数在执行遵循可能导致无法达到目标的路径或达到目标时立即终止。

我最初的方法是让branch-label 函数抛出特定类型的异常,然后我的搜索函数会捕获该异常,但后来我想到适应度函数本身可以捕获异常例如,如果在 try-catch 块中满足终止条件,则过早地出现。

例如假设我们在一个函数中有这个:

(try (if TEST THEN ELSE) (catch Exception _))

适应度函数类似于:

(try 
    (if TEST 
      (do (branch-label ...) THEN)
      (do (branch-label ...) ELSE))
    (catch Exception _))

因此,如果branch-label 在哪里抛出任何类型的异常,它将被吞没在这里,函数可能会继续运行。

我的另一个想法是在单独的线程上运行适应度函数并从分支标签函数内部调用(.stop (Thread/currentThread)),但似乎所有消息来源都说永远不应该使用 Thread.stop。

总而言之,我的问题是在 Clojure 通常的控制流机制之外,试图找到一种(相对)干净的方式来立即退出正在运行的函数。

【问题讨论】:

  • 返回一个表示条件的值?可以添加branch-label的相关代码吗?
  • @Lee branch-label 的返回值是不可访问的,因为它在分支本身之前的 do 块中被调用,因此它不会影响任何东西。代码的要点是:计算适应度并将其存储在适应度原子中,检查是否满足停止条件(即满足关键分支或目标),如果满足,则退出。
  • 您能否更新调用者以将其分配到 let/if-let 块中并在其上分支?如果您可以将代码添加到您的问题中会更清楚。
  • 我已经很长时间没有以这种方式摆弄 JVM,所以这不是答案,但我建议查看 JVM 提供的调试/仪表接口。您基本上想要做的是使用等效的断点来管理适应度函数的执行,并在函数本身带外确定的条件下终止执行。这就是调试器所做的。这种方法也应该意味着你不必重写函数来使用它来适应健身,这可能会很麻烦。听起来是个有趣的项目,祝你好运。

标签: clojure


【解决方案1】:

好的,所以我得出了我认为令人满意的解决方案。我没有使用Thread.stop,而是将适应度函数作为future 运行,并传递给它一个promise(它又被传递给branch-label)。然后主线程取消这个承诺(因此被阻塞)。达到停止条件后,最终的适应度被传递给 Promise,主线程被解除阻塞,并继续取消未来。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-07-29
    • 1970-01-01
    • 1970-01-01
    • 2012-06-23
    • 1970-01-01
    • 2011-12-07
    • 2011-02-07
    • 2015-05-28
    相关资源
    最近更新 更多