什么是谓词调度

Eli*_*der 25 oop predicate clojure

我最近在Clojure上看过很多关于谓词调度的讨论,并想知道这件事是否有什么东西.换句话说,什么是谓词调度,它与通用函数,OOP多态和模式有何不同?谢谢

dno*_*len 22

谓词调度包含泛型函数,OOP多态,模式匹配等.一个很好的概述是Predicate调度: Michael Ernst,Craig Kaplan和Craig Chambers的统一派遣理论.从它的摘要:

谓词调度通过允许任意谓词控制方法适用性并使用谓词之间的逻辑蕴涵作为覆盖关系来概括先前的方法调度机制.选择用于处理消息发送的方法不仅取决于参数的类,如在普通的面向对象的分派中,还取决于子组件的类,参数的状态以及对象之间的关系.


Stu*_*rra 15

编辑: Clojure multimethods不是谓词派遣.

在传统的面向对象编程中,多态意味着您可以拥有方法的多个实现,并且调用的确切实现由您调用该方法的对象的类型决定.这是类型调度.

Clojure multimethods对此进行了扩展,以便任意函数可以决定调用哪个实现.在Clojure表单中(defmulti name f),函数f调度函数.

调度函数可以是class,在这种情况下,您将返回类型调度.但该功能可能是其他任何功能:计算调度值,查找数据库中的内容,甚至调用Web服务.

真正的谓词调度可能允许每个方法实现指定一个或多个调度函数(谓词)来决定何时应用该方法.这比多方法更通用,但实现起来更复杂.Clojure不支持它.

通用函数是来自其他Lisp的术语.例如,Common Lisp提供了通用函数,可以在类型上调度,也可以使用一组受限制的其他函数.

  • 我发现这是一个误导性的答案,因为多方法并不是真正的谓词调度. (7认同)
  • Clojure没有适当的谓词调度系统.调度功能是硬连线的 - 潜在的扩展器无法添加原始调度功能尚未定义的新调度条件. (5认同)
  • 除非调度函数本身就是一个多方法!但确实您无法添加新的调度功能。 (2认同)

lus*_*ter 8

谓词调度是一种根据函数参数的数量,"形状"和值,为函数调用提供不同响应的方法.Clojure函数已经调度到不同的代码体,具体取决于传递给函数的参数数量:

(defn my-func
  ([a] (* a a))
  ([a b] (* a b)))
Run Code Online (Sandbox Code Playgroud)

Clojure multimethods增加了调度到不同方法的能力 - 可能在不同的命名空间中定义 - 基于调度参数(可以包括它们的数量,类和值)的调度函数的返回值,并确定所有方法.如Stuart Sierra的答案脚注中所述,多方法的创建者可以定义调度函数,通常不能修改它.此外,程序员必须为一个函数手工设计一个超复杂的调度函数,该函数对一个值为0的整数执行一个函数,对另一个正整数执行另一个函数.或者一个用于一个或多个项目的列表,另一个用于空列表.

谓词调度(可能)提供生成此复杂调度函数本身的语法.例如,可以通过这种方式定义阶乘函数

(defmatch fact [0] 1)
(defmatch fact [n] (* n (fact (dec n))))
Run Code Online (Sandbox Code Playgroud)

前一个代码响应一个调用

(fact 0)
Run Code Online (Sandbox Code Playgroud)

后一个代码用于具有任何其他值的单个参数的调用.这将(在幕后)定义具有调度函数的多方法,该函数将零与其他值区分开.

但后来我可以通过编码来指定我想要地图(可能)的因子

(defmatch fact [x {}] (fact (:value x)))
Run Code Online (Sandbox Code Playgroud)

并且代码可以(理论上)拦截将映射传递给事实的调用,将其他调用委托给原始调度函数......所有这些都在幕后进行.