Lisp 类终结:如何避免创建虚拟实例?

Lisp 类终结:如何避免创建虚拟实例?,lisp,common-lisp,clos,mop,Lisp,Common Lisp,Clos,Mop,我遇到了一个问题,第三方库需要对一个类执行操作,就好像它已经完成一样。经过一些阅读,我理解了这个机制背后的动机,但我真的不知道它是如何运作的 例如: (make-instance 'expression :op '+ :left 'nan :right 'nan) (defmethod normalize-expression ((this expression)) (optima:match this ((optima::or (expression :left 'nan) (ex

我遇到了一个问题,第三方库需要对一个类执行操作,就好像它已经完成一样。经过一些阅读,我理解了这个机制背后的动机,但我真的不知道它是如何运作的

例如:

(make-instance 'expression :op '+ :left 'nan :right 'nan)
(defmethod normalize-expression ((this expression))
  (optima:match this
    ((optima::or (expression :left 'nan) (expression :right 'nan)) 'nan)
    ((expression :op op :left x :right y) (funcall op x y))))
除非我添加第一行,否则函数将不会编译,从而导致以下错误:

; caught ERROR:
;   (during macroexpansion of (SB-PCL::%DEFMETHOD-EXPANDER NORMALIZE-EXPRESSION ...))
;   SB-MOP:CLASS-SLOTS called on #<STANDARD-CLASS EXPRESSION>, which is not yet finalized.
;   See also:
;     AMOP, Generic Function SB-MOP:CLASS-SLOTS
;捕获错误:
;   (在(SB-PCL::%DEFMETHOD-EXPANDER NORMALIZE-EXPRESSION…)的宏扩展期间)
;   SB-MOP:课程槽被称为#,尚未最终确定。
;   另见:
;     AMOP,通用函数SB-MOP:类槽
optima
是一个模式匹配库,
(expression:op-op…
将类
expression
的实例与给定模式进行匹配。我不知道太多的细节,但是看起来它需要知道为这个类定义的访问器是什么,而且在最终确定之前,这些信息是不可用的。那么,有没有办法避开定稿问题呢


这个类将不会被扩展(至少在这个项目中不会,而且它也没有被计划)。创建一个虚拟实例并没有太大的伤害。。。这只是一个丑陋的解决方案,所以我希望找到一个更好的解决方案。另外,也许,我会得到一些关于终结的更多信息,这也很好:)

在使用MOP时,忘记确保类终结似乎是非常常见的错误

在lisp中,类定义为两个“阶段”:

  • 直接类定义
  • 有效类定义
直接类定义同构于
defclass
形式。它有类名、超类名称、直接插槽列表(即,在这个特定类上定义的插槽,但在它的超类上定义的插槽)

有效的类定义包含编译器/解释器所需的所有信息。它包含所有类槽(包括在超类上定义的槽)、类实例布局、对访问器方法的引用等的列表

将直接类定义转换为有效类定义的过程称为类终结。由于CLOS支持重新定义类,因此可能会对一个类多次调用终结。终止延迟的原因之一是类可能在定义其超类之前定义

关于您的特殊问题:
optima:match
似乎应该确保在尝试列出其插槽之前完成类。这可以通过两个函数来完成:
class-finalized-p
(检查类是否需要终结)和
finalizeinheritation
实际执行终结。或者您可以使用实用程序功能
closer mop:sure finalized
。(closer mop是CLOS mop的便携使用库)

例如:

(c2mop:ensure-finalized (find-class 'expression))

谢谢你的回答!我相信
optima
已经导入了
closer-mop
,所以使用这个函数应该不会有问题。不过还有一件事:考虑到我的处境,以及某种“利益冲突”。如果需要,
optima
应该进行检查和定稿吗,还是由开发人员来完成?也就是说,坦率地说。这是一个
optima
错误,还是您通常希望库的用户在使用库之前解决这些问题?在这种情况下,我相信这是
optima
中的错误。我的经验法则是,如果我自己不使用拖把,我就不必担心拖把的内部结构。