Clojure的含义是支持多种分类法'与多态性有关?

时间:2014-09-12 20:01:25

标签: clojure

我一直在阅读' Clojure理由'这里:

http://clojure.org/rationale

在多态性部分中,它显示为:

Clojure multimethods decouple polymorphism from OO and types

   Supports multiple taxonomies
   Dispatches via static, dynamic or external properties, metadata, etc

&f;支持多种分类法的含义是什么?这里?事实上,在这种情况下,什么是分类?感谢

2 个答案:

答案 0 :(得分:5)

user> (defmulti shade :color)
nil
user> (defmethod shade :black [_] "darkest of darks")
#<MultiFn clojure.lang.MultiFn@22b90f93>
user> (defmethod shade :white [_] "all frequencies are reflected")
#<MultiFn clojure.lang.MultiFn@22b90f93>
user> (defmulti movement :legs)
#'user/movement
user> (defmethod movement 2 [_] "walks on hind legs")
#<MultiFn clojure.lang.MultiFn@13b58075>
user> (defmethod movement 4 [_] "proceeds on all fours")
#<MultiFn clojure.lang.MultiFn@13b58075>
user> ((juxt movement shade) {:name "cat" :legs 4 :color :black})
["proceeds on all fours" "darkest of darks"]

在上面的代码中,创建了两个组织系统 - 一个是颜色,另一个是腿。这两种分类法同样有效,根据所使用的分类法,同一对象可以分为不同的位置。

Multimethods也可以使用层次结构进行调度(参见derive和相关函数),其中每个层次结构可以并行共存(与类层次结构的统一视图不同)。

user> (derive ::manx ::cat)
nil
user> (defmulti favorite-treat :species)
#'user/favorite-treat
user> (defmethod favorite-treat ::cat [_] "Tuna")
#<MultiFn clojure.lang.MultiFn@264d27e6>
user> (derive ::indoor ::domestic)
nil
user> (defmulti activity :tameness)
#'user/activity
user> (defmethod activity ::domestic [_] "window watching")
#<MultiFn clojure.lang.MultiFn@1654bf3f>
user> ((juxt favorite-treat activity) {:species ::manx :tameness ::indoor})
["Tuna" "window watching"]

这里同样的小猫是两个等级的成员 - 一个是归化,另一个是遗传,并且可以通过适当的方式解决其方法。

此外,即使设置asid multimethods,通过derive创建的关系也支持多重继承,这与jvm Class heirarchy Clojure不同:

user> (derive ::foo ::bar)
nil
user> (derive ::foo ::baz)
nil
user> (derive ::quux ::foo)
nil
user> (isa? ::quux ::foo)
true
user> (isa? ::quux ::bar)
true
user> (isa? ::quux ::baz)
true
user> (isa? ::bar ::baz)
false

答案 1 :(得分:3)

与许多其他函数式语言一样,Clojure利用松散类型提供了实现parametric polymorphism的简单方法。这基本上意味着可以构造单个方法,使其不关心给出的参数的值类型。

concat方法为例。它需要不同形式的任意数量的参数,并将它们放入一个列表中,如下所示:

user=> (concat [:a :b] nil [1 [2 3] 4])
(:a :b 1 [2 3] 4)

因为一个人不需要为参数声明一个类型,所以concat可以用这样的方式编写,你可以提供任何类型的参数(向量,函数,关键字,字符串等)和它将以类似的方式对他们采取行动。

Clojure的multimethods允许您通过使用元数据或其他属性来确定处理给定参数的适当方式,从而在可能具有完全不同结构(即分类法)的Java对象上支持此概念。请参阅以下示例(摘自defmulti):

(defmulti greeting
  (fn[x] (x "language")))

(defmethod greeting "English" [params]
  (str "Hello! " (params "id")))
(defmethod greeting "French" [params]
  (str "Bonjour! " (params "id")))

=>(greeting {"id" "1", "language" "English"})
"Hello! 1"
=>(greeting {"id" "2", "language" "French"})
"Bounjour! 2"

greeting方法返回地图中的"language"值,该值与"English""French" defmethod匹配,返回正确的对应值。希望您能看到这个概念如何可能应用于任何类型的数据或对象结构。这种强大的多态性概念是Clojure开发人员试图在理由页面中展示的内容。