【问题标题】:Is there an idiomatic alternative to nil-punning in Clojure?Clojure 中是否有一个惯用的替代方法来替代 nil-punning?
【发布时间】:2016-04-09 03:28:11
【问题描述】:

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

现在有很多 Clo​​jure 库 treat this as idiomatic。这意味着它是一个公认的约定。

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

其他语言具有MaybeOption 的概念,以在值为空的情况下代理该值,作为减轻NullPointerException 风险的一种方式。这在 Clojure 中是可能的 - but not very common

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

另一种选择是将未初始化的值设置为:empty-value 之类的符号,以强制用户在所有处理代码中显式处理此场景。但这并不是nil 的一大进步——因为直到运行时您才真正发现所有场景(在其他人的代码中)。

我的问题是:在 Clojure 中是否有一个惯用的替代 nil-punning 的方法?

【问题讨论】:

    标签: clojure null maybe


    【解决方案1】:

    在 Clojure 中是否有一个惯用的替代方法来替代 nil-punning?

    没有。正如leeor 解释的那样,nil-punning 是惯用的。但它不像在 Common Lisp 中那样普遍,(我被告知)一个空列表等于 nil。

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

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

    【讨论】:

      【解决方案2】:

      不确定您是否在 nil-punning 上阅读过此 lispcast post,但我确实认为它很好地说明了为什么它是惯用的,并涵盖了我在其他 SO 中没有提到的各种重要考虑因素问题。

      基本上,nil 在 clojure 中是一个一流的东西。尽管它具有固有的传统含义,但它一个适当的值,并且可以在许多上下文中以与上下文相关的方式来处理。这使它比宿主语言中的null 更加灵活和强大。

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

      if(null) {
      ....
      }
      

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

      我认为您可以在处理实际nulls 的Java 互操作场景中很容易遇到问题。在许多情况下,一个好的 clojure 包装器库还可以帮助您避免这种情况,这是更喜欢在可能的情况下使用直接 java 互操作的一个很好的理由。

      有鉴于此,您可能需要重新考虑与这种潮流作斗争。但既然你问的是替代方案,我认为这是一个很棒的选择:prismatic's schema。 Schema 有一个Maybe 模式(以及许多其他有用的模式),它在许多场景中都非常好用。该库非常受欢迎,我已经成功使用它。 FWIW,推荐在最近的clojure applied一书中。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2021-11-06
        • 2023-03-21
        • 2022-01-01
        • 1970-01-01
        • 2015-02-12
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多