gpt4 book ai didi

error-handling - 具有故障形式的 clojure 线程宏

转载 作者:行者123 更新时间:2023-12-03 07:40:46 26 4
gpt4 key购买 nike

我有一些我想线程化的操作,每个操作都可能失败。我更愿意将错误作为一个值而不是使用破坏执行流程的 try-catch。

我可以做一个简单的版本,让我的函数使用 nil 作为失败:

(if-let (op1 ...)
(if-let (op2 ...)
...
err1)
err2)

但这是嵌套的,因此更难阅读。

我可以使用 some->这似乎是最接近的解决方案,但并没有说明失败的原因:
(if-let [res (some-> arg
op1
op2)]
res
somethin-failed) ;; what failed though?

我还看了 -> , 和 cond->但他们似乎没有帮助。

我知道网上有宏可以做这些事情,但如果有东西可以解决这个问题,我宁愿不添加宏。希望有一些形式:
(some-with-err-> arg
op1 err1
op2 err2
...)

我可能忽略了一些更简单的东西,但我似乎找不到内置的东西来解决这个问题。

我可以编写一个宏来做到这一点,但现在宁愿避免它。

最佳答案

没有内置任何东西,但是有一些用于单子(monad)错误处理的库(例如 Failjure ),这似乎是您正在寻找的。

你可以推导出一个版本 some-with-err->来自 some->宏定义。唯一实际的区别是 map绑定(bind)到 steps 的函数现在对表单/错误值进行分区,换行 step try 中的调用并在失败时返回命名空间映射:

(defmacro some-with-err->
[expr & forms]
{:pre [(even? (count forms))]}
(let [g (gensym)
steps (map (fn [[step error]]
`(if (or (nil? ~g) (::error ~g))
~g
(try (-> ~g ~step)
(catch Exception _# {::error ~error}))))
(partition 2 forms))]
`(let [~g ~expr
~@(interleave (repeat g) (butlast steps))]
~(if (empty? steps)
g
(last steps)))))

它可以像 some-> 一样使用但是每个表单都必须伴随一个错误返回值:
(some-with-err-> 1
(+ 1) :addition
(/ 0) :division
(* 2) :multiplication)
=> #:user{:error :division}

(some-with-err-> " "
(clojure.string/trim) :trim
(not-empty) :empty
(str "foo") :append)
=> nil ;; from not-empty

关于error-handling - 具有故障形式的 clojure 线程宏,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55258470/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com