假设我编写了以下代码(请原谅任何错误,我是 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/