【问题标题】:Class finalization: how to avoid creating dummy instances?类终结:如何避免创建虚拟实例?
【发布时间】:2013-07-29 20:48:13
【问题描述】:

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

例子:

(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

optima 是一个模式匹配库,(expression :op op ...)expression 类的实例与给定模式匹配。我不知道太多细节,但看起来它需要知道为这个类定义的访问器是什么,而且看起来这些信息在最终确定之前是不可用的。那么,有什么办法可以回避敲定问题呢?

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

【问题讨论】:

    标签: lisp common-lisp clos mop


    【解决方案1】:

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

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

    • 直接类定义
    • 有效的类定义

    直接类定义与defclass 形式同构。它具有类名、超类名称、直接槽列表(即,在该特定类上但在其超类上定义的槽)。

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

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

    关于您的特定问题:optima:match 似乎应该确保该类在尝试列出其插槽之前完成。这可以通过两个函数来完成:class-finalized-p(检查类是否需要终结)和finalize-inheritance 实际执行终结。或者你可以使用实用函数closer-mop:ensure-finalized。 (closer-mop 是一个可移植使用 CLOS MOP 的库)。

    例如:

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

    【讨论】:

    • 感谢您的回答!我相信optima 已经导入了closer-mop,所以使用这个函数应该不是问题。不过还有一件事:考虑到我的情况,以及某种“利益冲突”。如果需要,optima 是否应该进行检查和最终确定,还是由开发人员来做? IE。说白了。这是optima 错误,还是您通常希望库的用户在使用库之前解决此类问题?
    • 在这种情况下,我相信这是optima 中的一个错误。我的经验法则是,如果我自己不使用 MOP,我不应该担心 MOP 的内部结构。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-10-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-03-28
    相关资源
    最近更新 更多