Clojure 中的惯用错误处理

Posted

技术标签:

【中文标题】Clojure 中的惯用错误处理【英文标题】:Idiomatic error handling in Clojure 【发布时间】:2015-02-28 19:29:45 【问题描述】:

当我戴上 C 帽时,我想也许惯用的 Clojure 只是做简单的事情并检查返回值。

当我戴上 Java 帽子时(我很不情愿地,我必须补充一下),我对自己想,既然 Clojure 在 JVM 上运行,自然的方式必须是使用 JVM 异常。

当我戴上函数式帽子时,我在想一定有某种单子构造或线程宏可以以可组合的方式处理错误。

那么在 Clojure 程序中处理错误的惯用方法是什么?

【问题讨论】:

人们几乎觉得 Either monad 属于核心 Clojure。简单地抛出一个我认为很典型的异常,感觉就像是在回归到命令式的做事方式。 【参考方案1】:

Clojure 错误处理通常是面向 JVM 异常(未检查)的。

Slingshot 允许对抛出的异常值进行解构,从而使使用异常更加愉快。

对于允许 erlang 样式错误处理的替代方法,您应该查看 dire。 blog post 很好地概述了可怕的合理性以及 Clojure 错误处理机制和缺点的概述。

【讨论】:

原始链接重定向到一些奇怪的垃圾邮件。这是博客文章的存档链接:web.archive.org/web/20150301143918/http://… @mskoh52 谢谢,我现在也更新了答案中的链接【参考方案2】:

对于一个非常实用的方法,请查看cats,它对应于“某种单子结构”:

Clojure 和 ClojureScript 的类别理论和代数抽象。 http://funcool.github.io/cats/latest/

示例取自他们的文档:

(require '[cats.core :as m])
(require '[cats.monad.maybe :as maybe])

(m/mappend (maybe/just [1 2 3])
           (maybe/nothing)
           (maybe/just [4 5 6])
           (maybe/nothing))

您可以看到nothing 在某种程度上等同于nil,只是您不必手动检查任何内容。

【讨论】:

作为一个 Haskeller,我喜欢 faaaar 的 Maybe monad 方法,但我不认为它是惯用的 Clojure。 我只在 repl 中玩过猫,但我知道有些人在生产中使用它。还有github.com/uncomplicate/fluokitten,甚至可能是github.com/bwo/monads,但是那里有很多错误处理库(例如可怕和弹弓),所以这绝对感觉像是可以在核心语言中改进的东西。【参考方案3】:

Clojure 中错误处理的官方手段是异常,因为它是 JVM 自带的。但是,函数在抛出异常时不是引用透明的,而且这个属性也不是可组合的。异常不起作用。

许多人已经在 Clojure 中尝试了不同风格的替代/单元错误处理。为此,我创建了 Promenade https://github.com/kumarshantanu/promenade,并且有很好的使用经验。

【讨论】:

以上是关于Clojure 中的惯用错误处理的主要内容,如果未能解决你的问题,请参考以下文章

clojure 中的惯用配置管理?

惯用的节点错误处理

惯用节点错误处理

在golang中处理逻辑错误与编程错误的惯用方法

惯用的 goroutine 终止和错误处理

通过 Clojure 中的集合进行递归的惯用方式