Macros 在自定义宏中使用公共lisp defclass生成实例

Macros 在自定义宏中使用公共lisp defclass生成实例,macros,common-lisp,sbcl,clos,Macros,Common Lisp,Sbcl,Clos,我定义了一个宏来创建一个新类,然后定义了一个常量来创建新定义类的实例: (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-USE

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

(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>)
没有名为COMMON-LISP-USER::X1025的类。
[简单错误类型的条件]
重新启动:
0:[中止]中止编译。
1:[*中止]返回SLIME的顶层。
2:[移除-FD-HANDLER]移除#
3:[中止]退出调试器,返回顶层。
回溯:
0:(SB-PCL::FIND-CLASS-FROM-CELL X1025 NIL T)
1:((:方法生成实例(符号))X1025[快速方法]
2:(SB-INT:SIMPLE-EVAL-IN-lexev(MAKE-INSTANCE(引号X1025))#

编译时可能不知道该类,因此Lisp可以创建实例。该标准规定,在编译过程中应该知道类,但不能在实际执行
DEFCLASS
表单之前创建实例

defcontent
可以在编译时计算
MAKE-INSTANCE
表单。正如您在回溯中看到的,SBCL实际上尝试调用
MAKE-INSTANCE


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

在编译时,该类可能不为人所知,因此Lisp可以创建实例。该标准规定,在编译过程中应该知道类,但不能在实际执行
DEFCLASS
表单之前创建实例

defcontent
可以在编译时计算
MAKE-INSTANCE
表单。正如您在回溯中看到的,SBCL实际上尝试调用
MAKE-INSTANCE


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

在编译时,该类可能不为人所知,因此Lisp可以创建实例。该标准规定,在编译过程中应该知道类,但不能在实际执行
DEFCLASS
表单之前创建实例

defcontent
可以在编译时计算
MAKE-INSTANCE
表单。正如您在回溯中看到的,SBCL实际上尝试调用
MAKE-INSTANCE


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

在编译时,该类可能不为人所知,因此Lisp可以创建实例。该标准规定,在编译过程中应该知道类,但不能在实际执行
DEFCLASS
表单之前创建实例

defcontent
可以在编译时计算
MAKE-INSTANCE
表单。正如您在回溯中看到的,SBCL实际上尝试调用
MAKE-INSTANCE


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

Rainer回答得很好,通常也是这样。但是,我想警告您:“因此,用户必须确保初始值可以在编译时计算(无论文件中是否出现对name的引用),并且它总是计算为相同的值。”(CLHS,defconstant)。但是,每个
使实例
调用的计算值不相同。。。所以不应该在defcontain中使用make instance。使用defvar,不要修改它:)雷纳和往常一样回答得很好。但是,我想警告您:“因此,用户必须确保初始值可以在编译时计算(无论文件中是否出现对name的引用),并且它总是计算为相同的值。”(CLHS,defconstant)。但是,每个
使实例
调用的计算值不相同。。。所以不应该在defcontain中使用make instance。使用defvar,不要修改它:)雷纳和往常一样回答得很好。但是,我想警告您:“因此,用户必须确保初始值可以在编译时计算(无论文件中是否出现对name的引用),并且它总是计算为相同的值。”(CLHS,defconstant)。但是,每个
使实例
调用的计算值不相同。。。所以不应该在defcontain中使用make instance。使用defvar,不要修改它:)雷纳和往常一样回答得很好。但是,我想警告您:“因此,用户必须确保初始值可以在编译时计算(无论文件中是否出现对name的引用),并且它总是计算为相同的值。”(CLHS,defconstant)。但是,每个
使实例
调用的计算值不相同。。。所以不应该在defcontain中使用make instance。使用defvar,不要修改它:)