Common Lisp对象传递至方法时的类型匹配问题排查
问题根源分析与解决方案
我来帮你理清楚这个问题——核心原因是你在创建*state-1*时,给:my-cards参数传入的是符号列表,而不是game-cards实例的列表。
具体问题出在哪?
看你创建*state-1*的代码:
(defparameter *state-1* (make-instance 'game-states :my-cards '(*king-hearts* *ace-spades*) :other-cards ()))
这里的'(*king-hearts* *ace-spades*)是一个引用列表(单引号阻止了内部元素的求值),所以my-cards里存储的不是*king-hearts*和*ace-spades*这两个变量指向的game-cards实例,而是*KING-HEARTS*、*ACE-SPADES*这两个符号对象本身。
这就解释了所有现象:
- 直接调用
(some-job *king-hearts*)能正常运行:因为这里的*king-hearts*是变量,Lisp会自动解析它的值(也就是你创建的game-cards实例)。 - 执行
(first (my-cards *state-1*))得到*KING-HEARTS*:这里输出的是符号的名称,而不是实例(如果是实例,Lisp通常会显示类似#<GAME-CARDS {10039F8943}>的对象标识)。 - 调用
(some-job (first (my-cards *state-1*)))报错:因为你把符号*KING-HEARTS*传给了只接受game-cards实例的some-job方法,自然找不到适用的方法。同理,colour访问器也只能作用于game-cards实例,所以用defun定义的some-job-1也会报错。
解决方案
只需要去掉:my-cards参数里的单引号,让Lisp求值这两个变量,把实例对象存入列表:
(defparameter *state-1* (make-instance 'game-states :my-cards (*king-hearts* *ace-spades*) :other-cards ()))
这样my-cards里存储的就是两个game-cards实例,而不是符号。此时再调用(some-job (first (my-cards *state-1*)))就能正常返回HEARTS了。
内容的提问来源于stack exchange,提问作者N. Böck
相关产品推荐
相关产品推荐

