Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/clojure/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Interface 在Clojure中使用协议'描述分派是否准确;静态';?_Interface_Clojure_Static_Protocols_Dispatch - Fatal编程技术网

Interface 在Clojure中使用协议'描述分派是否准确;静态';?

Interface 在Clojure中使用协议'描述分派是否准确;静态';?,interface,clojure,static,protocols,dispatch,Interface,Clojure,Static,Protocols,Dispatch,在上写了一篇文章,标题是Static vs Dynamic。他写道: 协议不是我们在静态和动态之间进行权衡的唯一地方。有几个地方可以看到这样的权衡 他提供了协议中静态分派的以下示例: (defprotocol Flipable (flip [thing])) (defrecord Left [x]) (defrecord Right [x]) (extend-protocol Flipable Left (flip [this] (Right. (:x this))) Ri

在上写了一篇文章,标题是Static vs Dynamic。他写道:

协议不是我们在静态和动态之间进行权衡的唯一地方。有几个地方可以看到这样的权衡

他提供了协议中静态分派的以下示例:

(defprotocol Flipable
  (flip [thing]))

(defrecord Left  [x])
(defrecord Right [x])

(extend-protocol Flipable
  Left
  (flip [this] (Right. (:x this)))
  Right
  (flip [this] (Left. (:x this))))
现在,每个记录都映射到编译的JVM上的一个“类”,这是事实。如果您尝试在
左侧
右侧
之外的任何地方分派,您将得到
java.lang.IllegalArgumentException
,其中
没有为类找到方法:…的实现:…

我这样问是因为我的理解是Clojure在幕后有效地使用相同的JVM技术进行多态调度。我们可以将上述内容改写为:

interface Flippable {
  Flippable flip();
}

class Left implements Flippable {
  Right flip();
}

class Right implements Flippable {
  Left flip();
}

class Demo {
  public static void main(String args[]) {
    Flippable flippable = new Right();
    System.out.println(flippable.flip);
  }
}
现在,在编译和静态检查类型的同时,实际的调度是在运行时进行的


我的问题是:使用协议将Clojure中的调度描述为“静态”是否准确?(假设您没有使用映射进行调度,而是依赖于与类对应的记录或类型)

Clojure的协议实现是单分派类型驱动的多态性(函数的第一个参数的类型是多态的),因此是动态多态性的一种形式

使用
扩展协议
不会导致静态绑定。
extend协议
是一个宏,它只是扩展为一个
extend
调用:

(clojure.pprint/pprint
 (clojure.walk/macroexpand-all '(extend-protocol Flipable
                                  Left
                                  (flip [this] (Right. (:x this)))
                                  Right
                                  (flip [this] (Left. (:x this))))))

;=>     
(do
 (clojure.core/extend
  Right
  Flipable
  {:flip (fn* ([this] (new Left (:x this))))})
 (clojure.core/extend
  Left
  Flipable
  {:flip (fn* ([this] (new Right (:x this))))}))
正确的是,要调用的函数是使用底层JVM的动态调度机制在运行时动态确定的。这为协议提供了优于多方法的性能优势,同时将调度限制为第一个参数的类型

deftype
(或
reify
)定义中内联扩展协议与将协议扩展到现有类型(使用extend*变体)会导致性能差异。内联
deftype
与它实现的协议方法一起编译成Java类,因此直接实现协议方法

协议方法调用检查第一个参数是否直接实现协议,以及它是否直接在对象上调用方法,而不是查找适当的方法实现

还有一个详细的基准分析可用。Clojure源代码中的相关功能可用