common-lisp - 此 CLOS 代码是否会导致 Common Lisp 中出现运行时或编译时错误?

标签 common-lisp multiple-inheritance overriding clos

假设我编写了以下代码(请原谅任何错误,我是 Lisp 新手,我无法在这台机器上运行 CL)

(defclass o () ())
(defclass a (o) ())
(defclass b (o) ())
(defgeneric m (x))
(defmethod m ((x o))
   (print "O")
)
(defmethod m ((x a))
   (print "A")
   (call-next-method (make-instance 'a))
)
(defmethod m ((x b))
   (print "B")
   (call-next-method (make-instance 'b))
)

(setq aa (make-instance 'a))
(m aa) ;prints A, then O
(setq bb (make-instance 'b))
(m bb) ;prints B, then O

按照我的预期,它应该打印出评论中写的内容,没有任何提示。

如果我添加以下代码会发生什么?

(defclass c (a b) ())
(setq cc (make-instance 'c))
(m cc)

如果我了解标准方法组合,则 cc 的适用方法将排序为 (m a)(m b)(m o)(m b) 将不会被 call-next-method 成功调用。但实际上会发生什么呢?当我定义类 c 并说它使泛型函数 m 的方法链无效时,CL 会提示吗?或者会出现运行时错误吗?

最佳答案

编译时可能会失败。它很可能在运行时失败。

c 的对象的方法 m 顺序为:

(c a b o)

它将命中 a,其中将在 a 的新实例上调用下一个方法。 a 的方法 m 具有以下方法顺序:

(a o)

由于这些方法顺序不同,call-next-method 需要发出错误信号。 part of CLHS其中写到:

When providing arguments to call-next-method, the following rule must be satisfied or an error of type error should be signaled: the ordered set of applicable methods for a changed set of arguments for call-next-method must be the same as the ordered set of applicable methods for the original arguments to the generic function. Optimizations of the error checking are possible, but they must not change the semantics of call-next-method.

修复方法是不向 call-next-method 添加参数。编辑后,您可以在调用 (m cc) 时打印此内容:

"A" 
"B" 
"O" 

在 CLISP 中,它在运行时发出错误信号,而 SBCL 则不会,因此它实际上不符合 SBCL 中的规范。

关于common-lisp - 此 CLOS 代码是否会导致 Common Lisp 中出现运行时或编译时错误?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29969027/

相关文章:

lisp - 创建自定义列表反转

lisp - 调试级 Lisp

objective-c - 从 Objective C 中的两个类继承

php - 从两个父类继承

c++ - 功能覆盖不起作用

common-lisp - 选定的技术。 Web 应用程序堆栈 - 批评/评论?

lisp - 如何启动 Hunchentoot?

c++ - 通过具有多重继承的类向上转换 nullptr

java - Android @Override 用法

c++ - 遍历抽象类的 vector