Clojure seq作为Scala选项的替代品[T]

时间:2011-10-19 12:14:22

标签: scala clojure option seq

Scala提供了类Option[T]Some[T] extends Option[T]None extends Option[Nothing]的层次结构,我发现这些类包含了可以返回null的Java方法调用,其中包括:

val result = Option(someJavaMethodThatReturnsNull())

result的作用类似于零个或一个项目的序列,具体取决于Java方法是返回对象还是nullOptionmapfilter等方法,您可以像序列中的那些一样使用并返回新序列(Some),如果原始序列是如果原件为Some[T],则为NoneNone

Clojure函数seq的行为似乎相似:如果x为非空,则(seq x)将是一个项的序列;如果x为null,则nil将是(map ...)。然后,可以将此值传递到(filter ...)Option等,就像Scala {{1}}方法一样。

我错过了什么吗?这种模式有意义吗?这是“尤里卡!”那些对经验丰富的Clojure程序员来说很明显的时刻?

4 个答案:

答案 0 :(得分:2)

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

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

答案 1 :(得分: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也被认为是“假的”,因此可以方便地用于布尔操作。

答案 2 :(得分:1)

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

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

这是你想要的吗?

编辑:注意错误。

答案 3 :(得分:0)

如果(seq x)nil,则

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

以下各项将返回一个空序列:

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