目前,无法在 `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
` 不可能(或者说性能非常低,因此应该禁止使用)吗?或者它只是低优先级的用户体验特性,所以一直没有得到实现?