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

发布于 2024-12-11 02:01:06 字数 795 浏览 2 评论 0原文

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

val result = Option(someJavaMethodThatReturnsNull())

结果的行为就像一个由零个或一个项目组成的序列,具体取决于 Java 方法是否返回一个对象或nullOption 具有诸如 mapfilter 等方法,您可以像在序列上使用这些方法一样使用这些方法,也可以返回一个新序列(>Some),如果原始是 Some[T],或者 None 如果原始是 None

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

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

Scala offers a hierarchy of classes Option[T], Some[T] extends Option[T], and None extends Option[Nothing] that I have found useful for wrapping Java method calls that can return null, among other things:

val result = Option(someJavaMethodThatReturnsNull())

result acts like a sequence of zero or one items, depending on whether the Java method returned an object or null. Option has methods like map, filter, etc. that you can use just like those on a sequence and either return a new sequence (Some), if the original was Some[T], or None if the original was None.

It appears that the Clojure function seq behaves similarly: (seq x) will be a sequence of one item if x is non-null or nil if x is null. This value can then be passed to (map ...), (filter ...), etc., just like the Scala Option methods.

Am I missing something? Does this pattern make sense? Is this a "Eureka!" moment that is obvious to experienced Clojure programmers?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

自由如风 2024-12-18 02:01:06

You always could use the maybe monad, which is close to scala Option (and haskell Maybe) without static type safety of course.

Also there is the family of ? threading functions (.?. is the better choice for java interop)

鸵鸟症 2024-12-18 02:01:06

您当然可以使用 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 解释为空序列,因此遇到 NullPointerException 的可能性要小得多。
  • nil 也被认为是“错误的”,因此可以方便地用于布尔运算。

You can certainly use a Clojure sequence to represent zero, one or more return values.

It is a sensible approach and very idiomatic if your function is actually expected to return a collection.

However I would not recommend using a sequence to emulate an option type. This is likely to confuse users of your API. In Clojure, the normal and idiomatic way to is just to return nil if a value is not available, and return the value directly if it is.

Compare:

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

With what you would need if you used a sequence to emulate an option type:

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

I definitely prefer the first option.... why do we need or want the API user to unpack the result from the sequence with first?

In general, nil works pretty well in Clojure (much better than in other languages) because:

  • All the library functions interpret nil as an empty sequence, so you are much less likely to run into NullPointerExceptions.
  • nil is also considered "falsey" so can be conveniently used in boolean operations.
还在原地等你 2024-12-18 02:01:06

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

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

这就是你的意图吗?

编辑:谨防虚假信息。

No. seq will either return an abstract, sequential view on a collection in case the collection is non-empty. nil otherwise. So it is completely unrelated to what you want. However you can use nil in if tests. eg.

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

Is that what you intend?

Edit: Beware the false.

一抹淡然 2024-12-18 02:01:06

如果 xnil 或空集合,(seq x) 将返回 nil。然而,map、filter等将接受nil作为它们的集合参数(即它们不会中断)并返回一个空序列。这可能会给出您期望从 Scala 的 Option 语句得到的结果。

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

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

(seq x) will return nil if x is nil or an empty collection. However, map, filter etc. will accept nil as their collection argument (i.e., they won't break) and return an empty sequence. This may give the result that you expect from Scala's Option statement.

The following will each return an empty sequence:

(map (fn [x] x) (seq nil))
(map (fn [x] x) (seq `()))
(filter even? (seq nil))
(filter even? (seq `()))
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文