目前,无法在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 成为不可能(或者性能可能非常低,所以人们会避免这样做)?或者这仅仅是一个优先级较低的改善生活质量的功能,所以它从未得到实施?