4

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

val result = Option(someJavaMethodThatReturnsNull())

result根据 Java 方法返回的是对象还是null. Option具有 , 等方法mapfilter您可以像在序列上一样使用这些方法,并且如果原始序列是,或者如果原始序列是 ,则返回一个新序列 ( Some) 。Some[T]NoneNone

Clojure 函数的行为似乎seq相似:(seq x)如果 x 不为 null 或 x 为 null,则将是一个项目的序列nil。然后可以将该值传递给(map ...),(filter ...)等,就像 ScalaOption方法一样。

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

4

4 回答 4

2

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

还有家人吗?线程函数(.?. 是 Java 互操作的更好选择)

于 2011-10-19T15:46:25.387 回答
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 也被认为是“错误的”,因此可以方便地用于布尔运算。
于 2012-01-11T02:07:42.080 回答
1

seq,如果集合非空,则不会返回集合的抽象顺序视图。nil除此以外。所以它与你想要的完全无关。但是,您可以nil在 if 测试中使用。例如。

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

那是你的意图吗?

编辑:当心虚假。

于 2011-10-19T13:24:27.400 回答
0

(seq x)将返回nilif xisnil或空集合。但是,mapfilter将接受nil作为它们的集合参数(即它们不会中断)并返回一个空序列。这可能会给出您对 ScalaOption声明的预期结果。

以下将分别返回一个空序列:

(map (fn [x] x) (seq nil))
(map (fn [x] x) (seq `()))
(filter even? (seq nil))
(filter even? (seq `()))
于 2011-10-19T14:40:22.600 回答