为什么在Clojure中使用Maybe / Option没有这么普遍?

为什么Clojure尽pipe如此强调function范例,却不使用Maybe / Option monad来表示可选值? Scala是一个我经常使用的函数式编程语言,它的使用相当普遍。

Clojure没有静态types,所以不需要严格的haskell(和我收集,Scala)中必需的this / that /任何types的声明。 如果你想返回一个string,你会返回一个string; 如果你返回零,也没关系。

“function”并不完全对应于“严格编译时键入”。 它们是正交的概念,Clojureselectdynamictypes。 事实上,相当长一段时间,我无法想象如何实现许多像map这样的高阶函数,并且仍然保留静态types。 现在我对Haskell有一点(很less)的经验,我可以看到这是可能的,而且往往是相当优雅的。 我怀疑,如果你在Clojure上玩了一段时间,你将会有相反的经验:你会意识到types声明并不需要给你以function语言的那种力量。

在Clojure中,nil punning提供了Scala和Haskell从Option&Maybe获得的大部分function。

 **Scala** **Clojure** Some(1) map (2+_) (if-let [a 1] (+ 2 a)) Some(1) match { (if-let [a 1] case Some(x) => 2+x (+ 2 a) case None => 4 4) } 

Scala的选项和Haskell的可能都是Applicative的实例。 这意味着你可以在理解中使用这些types的值。 例如,Scala支持:

 for { a <- Some(1) b <- Some(2) } yield a + b 

Clojure的macros提供了对seq的理解。 不同于monadic理解,这个实现允许混合实例types。

虽然Clojure的for不能用于在多个可能的nil值上编写函数,但它的function是微不足道的。

 (defn appun [f & ms] (when (every? some? ms) (apply f ms))) 

并称之为:

 (appun + 1 2 3) #_=> 6 (appun + 1 2 nil) #_=> nil 

也许/选项是一种types。 它与函数式编程无关。 是的,有些语言(斯卡拉,哈斯克尔,ocaml)除了function还提供了一个非常强大的types系统。 人们甚至会说Haskell这是一个带有types的编程。

其他人(clojure,lisp)虽然是function完备的语言,但在types方面并不多。 他们的重点是不同的,可能/选项types不适合。它只是没有给你太多的dynamic语言。 例如,许多对序列(列表,向量,地图)进行操作的clojure函数将完全接受null(nil)并将其视为空结构。

(count nil)会给你0.就像(count [])

Clojure不能称为“types编程”,因此可能types没有多大意义。

重要的是要记住,Monad的概念不是关于types的! types系统帮助你执行规则(但即使Haskell也不能执行所有规则,因为它们中的一些(Monad定律)不能被types系统完全expression。

Monad是关于构图的,这是我们每天在每种编程语言中都做的非常重要的事情。 在任何情况下,Monad都会追踪一些关于正在发生的事情的“额外的上下文”……把它想象成一个能保留当前价值的盒子。 函数可以应用于这个值,额外的上下文可以作为一个正交的关注。

Maybetypes是关于将长序列的计算串联在一起,而不必对失败(这是“额外的上下文”)做任何说明。 这是一种将“error handling”从计算中移动到Monad中的模式。 你可以在一个Maybe上对一系列计算进行串联,只要一个失败,其余的就会被忽略,最后的结果就是“Nothing”。 如果他们都成功了,那么最终的结果就是monad拥有结果值。

这使您可以编写纠缠更less的代码。

Clojure支持Monad,就像@deterb指出的那样。

那么有一个Maybe monad,但它使用nil作为Nothing, 捕获计算的抽象(如果input = nil返回nil else计算任何与input)以避免空指针错误,但它没有静态编译时的安全性。 还有一个类似的任务,用缺省值和- ?>修零。 我认为clojure的方式更倾向于返回引起错误或零的默认值。

与@amalloy一起,并评论说,Clojure作为一种语言,不需要一个可选的返回值。

我对Scala没有太多的了解,但是Clojure并不需要知道关于返回types的严格细节,以便能够使用值。 就好像一个Maybe monad被embedded并且成为正常的Clojure评估的一部分,因为许多操作(如果在nil执行的话)返回nil

我快速浏览了一下Clojure-Contrib库,他们有一个monad包 ,你可能想看看。 另外一个真正让我知道如何在Clojure中使用Monad的项目是Cosmin在Clojure中Monad 的教程 。 正是这样,才能帮助我将Scala中更明确地阐述的function作为dynamicClojure语言的一部分进行处理。