【问题标题】:Clojure seq as a substitute for Scala Option[T]Clojure seq 作为 Scala Option[T] 的替代品
【发布时间】:2011-12-10 21:22:41
【问题描述】:

Scala 提供了 Option[T]Some[T] extends Option[T]None extends Option[Nothing] 类的层次结构,我发现它们对于包装可以返回 null 的 Java 方法调用很有用:

val result = Option(someJavaMethodThatReturnsNull())

result 的作用类似于零项或一项的序列,具体取决于 Java 方法返回的是对象还是 nullOption 具有 mapfilter 等方法,您可以像在序列上一样使用这些方法,如果原始序列是 Some[T]None,则返回新序列 (Some)如果原件是None

看起来 Clojure 函数 seq 的行为类似:如果 x 为非空,(seq x) 将是一个项目的序列,如果 x 为空,nil 将是一个序列。然后可以将该值传递给(map ...)(filter ...) 等,就像Scala 的Option 方法一样。

我错过了什么吗?这种模式有意义吗?这是一个“尤里卡!”对于有经验的 Clojure 程序员来说,这是显而易见的时刻?

【问题讨论】:

  • 附注:这种集合和选项(以及更多)的共享结构在 Haskell 中通过 FunctorFoldable 类捕获。

标签: scala clojure option seq


【解决方案1】:

你总是可以使用maybe monad,它接近于 scala Option(和 haskell Maybe),当然没有静态类型安全。

还有the family of ? threading functions(.?. 是java互操作的更好选择)

【讨论】:

    【解决方案2】:

    您当然可以使用 Clojure 序列来表示零个、一个或多个返回值。

    如果您的函数实际上期望返回一个集合,这是一种明智的方法并且非常惯用。

    但是我建议使用序列来模拟选项类型。这可能会使您的 API 用户感到困惑。在 Clojure 中,正常且惯用的方式是,如果值不可用则返回 nil,如果存在则直接返回值。

    比较:

      (if-let [a (function-that-returns-nil-or-result)]
        (do-something-with a))
    

    如果您使用序列来模拟选项类型,您将需要什么:

      (if-let [a (function-that-returns-a-possibly-empty-sequence)]
        (do-something-with (first a)))  
    

    我绝对更喜欢第一个选项....为什么我们需要或希望 API 用户使用 first 解压序列中的结果?

    一般来说,nil 在 Clojure 中工作得很好(比在其他语言中好得多),因为:

    • 所有库函数都将 nil 解释为空序列,因此您遇到 NullPointerExceptions 的可能性要小得多。
    • nil 也被认为是“错误的”,因此可以方便地用于布尔运算。

    【讨论】:

      【解决方案3】:

      没有。 seq 将在集合非空的情况下返回集合的抽象顺序视图。 nil 否则。所以它与你想要的完全无关。但是,您可以在 if 测试中使用 nil。例如。

      (when-let [thing (.someMethodThatReturnsSomethingOrNil other-thing)]
        (run-only-when thing is-not-nil-or-false))
      

      这是你想要的吗?

      编辑:谨防虚假。

      【讨论】:

      • 但是大多数(全部?)对序列进行操作的 Clojure 函数都接受 nil: (map nil) 等。在函数的“行尾”,您可能需要测试 nil,但在链式 if 调用中,您可以传递前一个函数返回的内容。
      • 但是seq 对你没有帮助,因为任意对象是不可排序的。 map 和朋友的工作水平与 Option 不同。我发现编写一个函数nil-safe 然后使用->comp 更容易。 YMMV。
      【解决方案4】:

      如果xnil 或空集合,(seq x) 将返回nil。但是,mapfilter 等将接受 nil 作为它们的集合参数(即它们不会中断)并返回一个空序列。这可能会给出您对 Scala 的 Option 语句所期望的结果。

      以下每个都将返回一个空序列:

      (map (fn [x] x) (seq nil))
      (map (fn [x] x) (seq `()))
      (filter even? (seq nil))
      (filter even? (seq `()))
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2011-04-04
        • 2021-08-31
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-11-08
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多