每当在 Haskell 中我们需要一些变体数据类型时,我们都会将 ADTs 与模式匹配结合使用。 Clojure 人们在此类用例中使用什么?
(defprotocol Fooable
(foo [x]))
(defrecord AType [avalue]
Fooable
(foo [x]
(println (str "A value: " (:avalue x)))))
(defrecord BType [avalue]
Fooable
(foo [x]
(println (str "B value: " (:bvalue x)))))
(foo (AType. "AAAAAA"))
=> A value: AAAAAA
(foo (BType. "BBBBBB"))
=> B value: BBBBBB
在这种情况下,协议有效地定义了您想要在 ADT 上进行的操作集,并且记录定义了 ADT 的可能值以及协议函数的多态行为。
matchure 库 - 它应该很快就会包含在 clojure-contrib 中
同时拥有关键字和符号的事实使得在模式匹配库之上实现变体变得非常容易。
下面是一个示例。
来源:那么它们在 Clojure 中看起来如何?
此 ADT 实现将使用的语法如下所示:
(defadt Tree (Empty) (Leaf value) (Node left right))
这个语法与 Haskell 代码非常相似。我们还将看到,我们可以像这样定义上面描述的深度函数:
(defmulti depth adt-type) (defmethod depth Empty [_] 0) (defmethod depth Leaf [_] 1) (defmethod depth Node [node] (+ 1 (max (depth (node :left)) (depth (node :right))))) (defmethod depth :default [_] 0)
http://gizmo385.github.io/clojure/programming/2015/08/11/adts-in-clojure.html