Lisp宏编译报错:无法找到slot-1通用函数适用方法,求解答
问题分析与解决
你遇到的核心问题
你写的宏在宏展开阶段就急着调用slot-1访问器,但此时*sample-instance*还只是个符号,根本没被求值成实际的类实例,Lisp当然找不到对应的通用函数方法啦。
为啥会出这错?
得先搞懂宏的两个关键阶段:
- 宏展开阶段:代码编译/解释时,Lisp会先把宏调用替换成展开后的代码,这一步在任何变量求值之前就完成了。
- 求值阶段:展开后的代码才会真正运行,此时变量才会被解析成具体值,函数才会被调用。
看你写的宏:
(defmacro sample-macro (p) `(if (typep ,p 'sample-class) (progn (print "evaluated") (print ,(slot-1 p)))))
这里的,(slot-1 p)是个致命错误——反引号里的,(...)会让Lisp在宏展开时就执行这个表达式。此时p是你传的符号*sample-instance*,不是实例对象,slot-1作为实例访问器,自然找不到能处理符号的方法,直接报错。
怎么改?
你要让(slot-1 p)在求值阶段才执行,也就是让它成为展开后代码的一部分,而不是在展开时就跑。只需要把,(slot-1 p)改成(slot-1 ,p)就行:
(defmacro sample-macro (p) `(if (typep ,p 'sample-class) (progn (print "evaluated") (print (slot-1 ,p)))))
这样宏展开后,最终执行的代码是:
(if (typep *sample-instance* 'sample-class) (progn (print "evaluated") (print (slot-1 *sample-instance*))))
到了求值阶段,*sample-instance*已经被解析成sample-class的实例,slot-1就能正常调用,取出插槽里的值了。
测试修正后的完整代码
把所有代码放一起跑:
(defclass sample-class () ((slot-1 :accessor slot-1 :initform "sample slot"))) (defvar *sample-instance* (make-instance 'sample-class)) (defmacro sample-macro (p) `(if (typep ,p 'sample-class) (progn (print "evaluated") (print (slot-1 ,p))))) (sample-macro *sample-instance*)
会输出:
"evaluated" "sample slot"
完美符合预期。
内容的提问来源于stack exchange,提问作者cstml
相关产品推荐
相关产品推荐

