如何解决Clozure Common Lisp 中的 Sharpsign 点宏
我想在 case 宏中使用常量变量作为“Common Lisp Recipes”一书的推荐。
- 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 很乐意为我加载这个文件的源代码,我相信任何 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"))
是合法的。然而,我可能错了:我已经很长时间没有从法庭上阅读规范了。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。