Clozure Common Lisp 中的 Sharpsign 点宏
Sharpsign dot macro in Clozure Common Lisp
我想按照“Common Lisp Recipes”一书的建议在 case 宏中使用常量变量。
- 10-2。在 CASE 宏中使用常量变量作为键
不幸的是,它在 Clozure CL 中不起作用。
(defpackage #:foo
(:use #:cl))
(in-package #:foo)
(defconstant +one+ 1)
(defconstant +two+ 2)
(defun lol (gg)
(ecase gg
(#.+one+ :one)
(#.+two+ :two)))
此代码加载失败。
Unbound variable: FOO::+ONE+
[Condition of type UNBOUND-VARIABLE]
Restarts:
0: [CONTINUE] Retry getting the value of FOO::+ONE+.
1: [USE-VALUE] Specify a value of FOO::+ONE+ to use this time.
2: [STORE-VALUE] Specify a value of FOO::+ONE+ to store and use.
该代码在 SBCL 中运行良好。为什么它在 CCL 中不起作用?
我在 macOS 上使用 64 位 Clozure CL 1.12。
CCL 会很乐意为我加载此文件的 source,我相信任何 CL 都应该这样做。
它不会做的,如果有任何 CL 会做,我会感到惊讶的是,编译它。它不会编译它,因为 defconstant
在编译时没有定义常量。这意味着,当编译 lol
时,会引用一个尚未定义的变量。
如果你想像这样处理常量,你需要确保变量是在编译时定义的。有两种方法:
首先你可以添加合适的eval-when
ery,之后相关的源代码块将是:
(eval-when (:compile-toplevel :load-toplevel :execute)
(defconstant +one+ 1)
(defconstant +two+ 2))
(defun lol (gg)
(ecase gg
(#.+one+ :one)
(#.+two+ :two)))
第二种是将常量放在自己的文件中,在使用前编译并加载。通常,这是使用 ASDF 等系统定义工具进行管理的。
注意:我相信任何 CL 都应该能够加载源代码,因为我认为,在加载源代码文件时,甚至需要仅编译器的实现,一次将它们视为一种形式:我不换句话说,不认为将 (load "foo.lisp")
变成 (load (compile-file "foo.lisp"))
是合法的。然而,我对此可能是错误的:我已经有很长时间没有从法庭上阅读规范了。
我想按照“Common Lisp Recipes”一书的建议在 case 宏中使用常量变量。
- 10-2。在 CASE 宏中使用常量变量作为键
不幸的是,它在 Clozure CL 中不起作用。
(defpackage #:foo
(:use #:cl))
(in-package #:foo)
(defconstant +one+ 1)
(defconstant +two+ 2)
(defun lol (gg)
(ecase gg
(#.+one+ :one)
(#.+two+ :two)))
此代码加载失败。
Unbound variable: FOO::+ONE+
[Condition of type UNBOUND-VARIABLE]
Restarts:
0: [CONTINUE] Retry getting the value of FOO::+ONE+.
1: [USE-VALUE] Specify a value of FOO::+ONE+ to use this time.
2: [STORE-VALUE] Specify a value of FOO::+ONE+ to store and use.
该代码在 SBCL 中运行良好。为什么它在 CCL 中不起作用?
我在 macOS 上使用 64 位 Clozure CL 1.12。
CCL 会很乐意为我加载此文件的 source,我相信任何 CL 都应该这样做。
它不会做的,如果有任何 CL 会做,我会感到惊讶的是,编译它。它不会编译它,因为 defconstant
在编译时没有定义常量。这意味着,当编译 lol
时,会引用一个尚未定义的变量。
如果你想像这样处理常量,你需要确保变量是在编译时定义的。有两种方法:
首先你可以添加合适的eval-when
ery,之后相关的源代码块将是:
(eval-when (:compile-toplevel :load-toplevel :execute)
(defconstant +one+ 1)
(defconstant +two+ 2))
(defun lol (gg)
(ecase gg
(#.+one+ :one)
(#.+two+ :two)))
第二种是将常量放在自己的文件中,在使用前编译并加载。通常,这是使用 ASDF 等系统定义工具进行管理的。
注意:我相信任何 CL 都应该能够加载源代码,因为我认为,在加载源代码文件时,甚至需要仅编译器的实现,一次将它们视为一种形式:我不换句话说,不认为将 (load "foo.lisp")
变成 (load (compile-file "foo.lisp"))
是合法的。然而,我对此可能是错误的:我已经有很长时间没有从法庭上阅读规范了。