Clojure seq替代Scala期权[T]
Scala提供了一个类的层次结构,Clojure seq替代Scala期权[T],scala,clojure,option,seq,Scala,Clojure,Option,Seq,Scala提供了一个类的层次结构,Option[T],Some[T]扩展Option[T],以及None扩展Option[Nothing],我发现这些类对于包装可以返回null的Java方法调用非常有用 val result = Option(someJavaMethodThatReturnsNull()) result的行为类似于零项序列或一项序列,这取决于Java方法是返回对象还是null选项具有类似于映射、过滤器等的方法。您可以像序列上的方法一样使用这些方法,如果原始序列是Some[T]
Option[T]
,Some[T]扩展Option[T]
,以及None扩展Option[Nothing]
,我发现这些类对于包装可以返回null
的Java方法调用非常有用
val result = Option(someJavaMethodThatReturnsNull())
result
的行为类似于零项序列或一项序列,这取决于Java方法是返回对象还是null
选项
具有类似于映射
、过滤器
等的方法。您可以像序列上的方法一样使用这些方法,如果原始序列是Some[T]
,则返回新序列(Some
),或者如果原始序列是None
Clojure函数seq
的行为似乎类似:(seq x)
如果x为非null,则为一项序列;如果x为null,则为nil
。然后可以将该值传递给(map…
,(filter…
)等,就像Scala选项
方法一样
我错过什么了吗?这种模式有意义吗?对于有经验的Clojure程序员来说,这是一个显而易见的“妙不可言”时刻吗?否。
seq
将在集合非空的情况下返回集合的抽象顺序视图<代码>无否则。所以这与你想要的完全无关。但是,您可以在if测试中使用nil
。例如
(when-let [thing (.someMethodThatReturnsSomethingOrNil other-thing)]
(run-only-when thing is-not-nil-or-false))
这就是你的意图吗
编辑:注意错误。(seq x)
如果x
是nil
或空集合,则将返回nil
。但是,map
,filter
等将接受nil
作为其集合参数(即,它们不会中断),并返回空序列。这可能会给出Scala的选项
语句所期望的结果
以下各项将返回一个空序列:
(映射(fn[x]x)(顺序为零))
(图(fn[x]x)(seq`())
(过滤器偶数?(顺序为零)
(筛选偶数?(seq`())
您始终可以使用,这接近scala选项(可能还有haskell),当然没有静态类型安全性
还有(.?.是java互操作的更好选择)您当然可以使用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用户先用解压序列中的结果
一般来说,nil在Clojure中工作得非常好(比其他语言好得多),因为:
- 所有库函数都将nil解释为空序列,因此您不太可能遇到NullPointerException
- nil也被认为是“错误的”,因此可以方便地用于布尔运算
旁注:这种集合和选项(以及更多)的共享结构通过and类在Haskell中捕获。但是大多数(全部?)在序列上操作的Clojure函数接受nil
:(map nil)
,等等。在函数的“行尾”处,您可能需要测试nil,但如果调用,您可以只传递上一个函数返回的内容。但是seq
对您没有帮助,因为任意对象是不可排序的<代码>地图
和朋友的工作级别与选项
不同。我发现编写一个函数nil
-安全,然后只使用->
和comp
更容易。YMMV。