什么是谓词调度

| 最近,我在Clojure上看到了很多有关谓词分发的讨论,并且想知道这件事是否有事。换句话说,谓词调度是什么,它与泛型函数,OOP多态性和模式有何不同? 谢谢     
已邀请:
编辑:Clojure多重方法不是谓词调度。 在传统的面向对象程序设计中,多态意味着您可以具有一个方法的多个实现,并且所调用的确切实现取决于调用该方法的对象的类型。这是类型调度。 Clojure多方法对此进行了扩展,以便任意函数可以确定调用哪个实现。在Clojure格式
(defmulti name f)
中,函数
f
是分派函数。 调度功能可能是
class
,在这种情况下,您将返回到类型调度。但是该功能可以做任何其他事情:计算调度值,在数据库中查找内容,甚至调出Web服务。 真正的谓词分派可能会允许每个方法实现指定一个或多个分派函数(谓词)来决定何时应用该方法。这比多方法更通用,但实现起来更复杂。 Clojure不支持它。 泛型函数是其他Lisps的术语。例如,Common Lisp提供了可以按类型分派的泛型函数以及一组受限制的其他函数。     
谓词调度包含泛型函数,OOP多态性,模式匹配等。谓词调度是一个很好的概述:迈克尔·恩斯特,克雷格·卡普兰和克雷格·钱伯斯的统一调度理论。从其摘要:   谓词分派通过允许任意谓词控制方法的适用性,并通过使用谓词之间的逻辑含义作为优先关系来概括以前的方法分派机制。选择用于处理消息发送的方法不仅可以像在普通的面向对象的分派中那样依赖于参数的类,还可以取决于子组件的类,参数的状态以及对象之间的关系。     
谓词分派是一种基于数字,“ shape”和函数自变量的值对函数调用提供不同响应的方式。 Clojure函数已经分派给不同的代码体,具体取决于传递给该函数的参数数量:
(defn my-func
  ([a] (* a a))
  ([a b] (* a b)))
Clojure多方法为此增加了基于调度函数的返回值来调度到不同方法(可能是在不同名称空间中定义)的能力,该函数检查参数(可以包括参数的编号,类和值)并识别所有方法。正如斯图尔特·塞拉(Stuart Sierra)答案的脚注所指出的那样,多重方法的创建者可以定义调度功能,并且通常无法对其进行修改。另外,程序员必须为一个函数手动设计一个超复杂的调度函数,该函数对一个值为0的整数执行一个操作,对一个正整数执行一个操作。或一件事代表一个或多个项目的列表,另一件事代表一个空列表。 谓词分派将(也许)提供一种语法,该语法本身会生成此复杂的分派函数。例如,可以通过这种方式定义阶乘函数
(defmatch fact [0] 1)
(defmatch fact [n] (* n (fact (dec n))))
前一个代码响应对的调用
(fact 0)
后者编码为带有任何其他值的单个参数的调用。这将(在幕后)定义一个带有调度功能的多方法,该功能将零与其他值区分开。 但是稍后我可以通过编码来指定我想要一个阶乘(例如)
(defmatch fact [x {}] (fact (:value x)))
并且代码可以(理论上)拦截将地图传递给事实的调用,将其他调用委派给原始分派函数...全部在幕后。     
为了将谓词分派与多方法进行对比,这有点像您在没有指定分派fn的情况下定义了多方法:
(defmulti my-method)
并且,当您想要扩展它时,您无需指定调度值(因为没有派生fn来生成它),而是一个谓词:
(defmethod my-method (fn [a b] (and (vector? a) (vector? b)))
  [a b]
  (do something))
简单而强大。 问题在于谓词可能重叠,而且您不想在每次调用时检查所有可能的谓词。这就是为什么实现会限制谓词的表达能力(类似于模式案例),以便能够对谓词保持精明(检测歧义,创建快速决策树等)。     

要回复问题请先登录注册