【问题标题】:Understanding Generic Functions in Common Lisp?了解 Common Lisp 中的泛型函数?
【发布时间】:2022-11-17 17:27:01
【问题描述】:

在这个answer 中,用户给出了一个非常清楚的例子,说明类和方法如何协同工作。

我将在这里转载示例:


(defclass human () ())
(defclass dog () ())

(defmethod greet ((thing human))
  (print "Hi human!"))

(defmethod greet ((thing dog))
  (print "Wolf-wolf dog!"))

(defparameter Anna (make-instance 'human))
(defparameter Rex (make-instance 'dog))

(greet Anna) ;; => "Hi human"
(greet Rex)  ;; => "Wolf-wolf dog!"

我的问题是,使用相同的示例:

  1. 创建通用函数会增加什么价值?
  2. 为什么泛型函数有用?它们是否像其他 OO 语言中提供结构的实例?

    似乎通用函数是在后台隐式创建的(不是 100% 确定)。我注意到,当我玩这个例子时,如果我创建的方法的参数结构与该方法的第一个实例不同,我会得到一个 generic function error

【问题讨论】:

标签: function class methods common-lisp sbcl


【解决方案1】:

DEFMETHOD 创建一个通用函数(如果不存在)。

显式定义通用函数让我们选择一些选项。

方法的参数列表必须使用一些规则。例如,特定泛型函数的方法的参数列表都需要具有相同数量的必需参数。

通用函数及其是 CLOS 中 OO 行为的基本结构。 CLOS 使用更适合 Lisp 的函数而不是虚拟方法或消息。

【讨论】:

  • 这也意味着我不需要显式定义通用函数。我可以根据我的实现思路创建方法和类吗?
【解决方案2】:

创建通用函数会增加什么价值?

我喜欢显式声明通用函数,因为您可以添加文档并在必要时指定其他细节,例如方法组合(也就是当您有多个适用于给定调用的方法时,这定义了执行的方法和顺序)。例如,我可以将 talk 定义为具有 progn 方法组合(所有方法都被执行,就像封装在 progn 形式中一样:

(defgeneric talk (subject)
  (:documentation "Print a talking message to standard output")
  (:method-combination progn))

这是一个有点人为的例子,但我们开始吧:

(defclass human ()())
(defmethod talk progn ((a human))
  (print "hello"))

(defclass wolf ()())
(defmethod talk progn ((a wolf))
  (print "owooooo!"))

然后,定义一个从两者继承的类意味着调用 talk 为类的实例可以执行两个方法(按某种拓扑顺序排序,称为方法解析顺序)。因此,使用此方法组合,将执行所有方法:

(defclass werewolf (human wolf) ())

在 REPL 中:

* (talk (make-instance 'werewolf))
"hello" 
"owooooo!"

但是,我要说的是,能够记录通用函数本身就足以成为使用 defgeneric 声明它的充分理由。

为什么泛型函数有用?

如果将 talk 定义为通用函数,则允许任何类参与调用 talk 的代码(例如库),这是一种允许扩展而不必关闭可能值集的方法(不同于使用 @987654332 @ 在您只能列出一组预定义类型的函数中)。

例如,标准函数 print-object 在您的 Lisp 实现中(在检查器、REPL、调试器中)的不同时间被调用,如果您愿意,您可以为您的自定义类型实现一个方法,而不必破解您环境的内部结构.

它们是否像其他 OO 语言中提供结构的实例?

与其他 OO 语言不同,泛型函数不绑定到单个类或实例。它们可以针对多个参数进行专门化,这意味着它们都不“拥有”通用函数。

【讨论】:

    猜你喜欢
    • 2017-07-26
    • 2012-08-13
    • 2014-10-24
    • 1970-01-01
    • 1970-01-01
    • 2017-10-19
    • 2020-08-16
    • 1970-01-01
    相关资源
    最近更新 更多