【问题标题】:common lisp defclass make-instance usage in custom macro自定义宏中的常见 lisp defclass make-instance 用法
【发布时间】:2014-03-22 21:40:06
【问题描述】:

我定义了一个宏来创建一个新类,然后定义一个常量来创建新定义的类的实例:

(defmacro my-class (name inst)
  `(progn
     (defclass ,name nil nil)
     (defconstant ,inst (make-instance ',name)))))

这似乎在 REPL 中有效

(my-class x1025 y1025)

但是在文件中编译时不起作用:

There is no class named COMMON-LISP-USER::X1025.
   [Condition of type SIMPLE-ERROR]

Restarts:
  0: [ABORT] Abort compilation.
  1: [*ABORT] Return to SLIME's top level.
  2: [REMOVE-FD-HANDLER] Remove #<SB-IMPL::HANDLER INPUT on descriptor 8: #<CLOSURE (LABELS SWANK-BACKEND::RUN :IN SWANK-BACKEND:ADD-FD-HANDLER) {13228535}>>
  3: [ABORT] Exit debugger, returning to top level.

Backtrace:
  0: (SB-PCL::FIND-CLASS-FROM-CELL X1025 NIL T)
  1: ((:METHOD MAKE-INSTANCE (SYMBOL)) X1025) [fast-method]
  2: (SB-INT:SIMPLE-EVAL-IN-LEXENV (MAKE-INSTANCE (QUOTE X1025)) #<NULL-LEXENV>)

【问题讨论】:

  • Rainer 回答得很好,和往常一样。但是,我想警告您:“因此,用户必须确保可以在编译时评估初始值(无论文件中是否出现对名称的引用)并且它始终评估为相同的值。” (CLHS,去常数)。但是,每个make-instance 调用都会评估为不同的值......所以你不应该在defconstant 中使用make-instance。使用 defvar,不要修改它:)

标签: macros common-lisp sbcl clos


【解决方案1】:

在编译期间可能不知道该类,这样 Lisp 可以创建实例。该标准规定在编译期间应该知道该类 - 但不是在实际执行 DEFCLASS 表单之前可以创建实例。

DEFCONSTANT 可能会在编译期间评估MAKE-INSTANCE 表单。正如您在回溯中看到的,SBCL 实际上尝试调用MAKE-INSTANCE

您需要在编译期间使该类完全可用。请参阅EVAL-WHEN 或将类声明放在另一个文件中,您需要先加载该文件。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-01-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-12-10
    • 1970-01-01
    相关资源
    最近更新 更多