gpt4 book ai didi

function - 了解 Common Lisp 中的泛型函数?

转载 作者:行者123 更新时间:2023-12-05 08:24:41 26 4
gpt4 key购买 nike

在此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. 创建通用函数会增加什么值(value)?
  2. 为什么泛型函数有用?它们是否类似于其他 OO 语言中提供结构的实例?

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

最佳答案

What value would creating a generic functions add?

我喜欢显式声明通用函数,因为可以添加与通用函数相关的文档声明(针对速度/空间/调试进行优化) ,以及其他详细信息,例如方法组合(也就是当您有多种方法适用于给定调用时,这定义了执行的方法和顺序)。例如,我可以将 talk 定义为具有 progn 方法组合(所有方法都被执行,就像封装在 progn 形式中一样):

(defgeneric talk (subject)
(:documentation "Say something to standard output")
(:method-combination progn))

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

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

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

(defclass werewolf (human wolf) ())

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

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

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

Why are generic functions useful?

如果将 talk 定义为通用函数,则允许任何类参与调用 talk 的代码(例如库),这是一种允许扩展的方法,无需必须关闭可能值的集合,这与在只能列出一组预定义案例的函数中使用类似 typecase 的东西不同。

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

Are they like instances in other OO languages that provide structure?

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


1specialized 被定义为 as follows :

specialize v.t. (a generic function) to define a method for the generic function, or in other words, to refine the behavior of the generic function by giving it a specific meaning for a particular set of classes or arguments.

这背后的想法是方法可以或多或少是特定的:一个方法有两个参数 ab 专门针对 (a number) (b string) 比另一个只专注于 (b vector) 的方法更具体,方法实际上是从最具体到最不具体的排序特定的(分别从最少到最多)组合它们时。您甚至可以在 (a (eql 10)) 上专门化一个函数,以仅涵盖参数 aeql 到 10 的特定情况。

关于function - 了解 Common Lisp 中的泛型函数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/74471770/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com