目前,无法在`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`中的最后一个表达式似乎是一个尾部表达式。
是否有技术限制使穿越`try`的`recur`变得不可能(或者可能性能非常低,因此认为这是阻止它的好主意)?或者这只是低优先级的特性,因此从未实现过?