在Clojure中是否存在一种惯用的替代方法?

时间:2016-01-05 10:28:26

标签: clojure null maybe

我正在阅读一些Clojure代码,其中有一堆未初始化的值为nil,用于传递的记录中的数值。

现在有很多Clojure库treat this as idiomatic。这意味着它是一个公认的惯例。

但它也导致NullPointerException,因为并非所有Clojure核心函数都可以处理nil作为输入。 (也不应该)。

其他语言具有MaybeOption的概念,以便在值为空时代理值,以减轻NullPointerException风险。这在Clojure中是可能的 - but not very common

您可以使用fnil做一些技巧,但它并不能解决所有问题。

另一种方法是简单地将未初始化的值设置为:empty-value之类的符号,以强制用户在所有处理代码中显式处理此场景。但这并不是nil的一个重大提升 - 因为在运行时之前你并没有真正发现所有场景(在其他人的代码中)。

我的问题是:在Clojure中是否有一种惯用的替代方法?

2 个答案:

答案 0 :(得分:6)

不确定您是否已经在nil-punning上阅读了这个lispcast post,但我确实认为这是一个非常好的理由,为什么它是惯用的,涵盖了各种重要的考虑因素,我没有在其他SO问题中看到过提及。

基本上,nil是clojure中的第一类事物。尽管它具有固有的常规含义,但它一个适当的值,并且可以在许多上下文中以及依赖于上下文的方式处理。这使得它比宿主语言中的null更灵活,更强大。

例如,像这样的东西甚至不能在java中编译:

if(null) {
....
}

在clojure中,(if nil ...)可以正常工作。所以在很多情况下你可以使用nil 安全。我还没有看到一个代码如if(foo != null) { ...无处不在的 的java代码库。也许java 8' Optional会改变这种情况。

我认为你可以很容易遇到问题的地方是你正在处理实际null的java互操作场景。在很多情况下,一个好的clojure包装器库也可以帮助你屏蔽它,并且它有一个很好的理由更喜欢一个而不是直接的java互操作。

鉴于此,您可能需要重新考虑对抗此电流。但既然你在询问替代方案,我认为这很好:prismatic's schema。 Schema有一个Maybe模式(以及许多其他有用的模式),它在很多场景中运行得非常好。该图书馆非常受欢迎,我已成功使用它。 FWIW,最近在clojure applied书中推荐。

答案 1 :(得分:2)

在Clojure中是否有一种惯用的替代方法?

没有。正如leeor所解释的那样,nil-punning是惯用的。但它并不像Common Lisp那样流行,其中(我被告知)空列表等于nil。

Clojure曾经以这种方式工作,但处理列表的CL函数对应于一般处理序列的Clojure函数。并且这些序列可能是懒惰的,因此将懒惰序列与其他序列统一是非常有用的,因此可以保留任何懒惰。我认为这种演变发生在Clojure 1.2上。 Rich详细描述了here

如果您想要选项/类型,请查看core.typed库。与Prismatic Sc​​hema相比,它在编译时运行。