目前无法在`try`块中进行`recur`。
(let [RETRIABLE-FUNCTION (fn [] (println "Function called") (throw (ex-info "Function failed" {})))]
(loop [retries 3]
(try
(RETRIABLE-FUNCTION)
(catch Exception ex
(when (< 1 retries)
(recur (dec retries)))))))
Syntax error (UnsupportedOperationException) compiling recur at (src/repl.clj:7:13). Can only recur from tail position
因此,人们不得不将代码重写为类似以下的内容:
(let [RETRIABLE-FUNCTION (fn [] (println "Function called") (throw (ex-info "Function failed" {})))]
(loop [retries 3]
(let [result (try
(RETRIABLE-FUNCTION)
(catch Exception ex
(when (< 1 retries)
::retry)))]
(if (= ::retry result)
(recur (dec retries))
result))))
这相当不方便,尤其是在嵌套重试或更复杂的状态机的情况下。
或者,可以使用很多重试宏库之一—我认为这给如此简单的用例带来的代价相当高。而且通常没有直接操作那么灵活。
从意识形态上讲,我觉得这里应该存在问题,因为`catch`中的最后一个表达式在我看来看起来像尾递归。
是不是JVM的技术限制使得跨`try`的`recur`变得不可能(或者可能性能非常低,所以人们应该避免这样做)?或者这只是一个优先级较低的生活质量特性,所以从未实现过?