我想在我正在创建的程序包中定义一个名为“ defun”的宏,我想将其导出以在某些地方使用。像这样,在程序包中有一个名为parenscript的库,
(export #:defun)
当我尝试在自己的包装中执行此操作时,出现此SBCL错误
Lock on package COMMON-LISP violated when defining DEFUN as a macro while in package COMMON-LISP-USER.
这在parenscript库中如何完成?我知道您可以输入表格;
(ps (defun function-name (args) (body)))
我希望能够做到这一点,但无法弄清楚该怎么做?
答案 0 :(得分:3)
您要隐藏CL包中的原始符号。
CL-USER 1 > (defpackage "MY-PACKAGE" (:use "CL"))
#<The MY-PACKAGE package, 0/16 internal, 0/16 external>
CL-USER 2 > (in-package "MY-PACKAGE")
#<The MY-PACKAGE package, 0/16 internal, 0/16 external>
MY-PACKAGE 3 > (shadow 'defun)
T
MY-PACKAGE 4 > (cl:defun defun () :my-defun-returns)
DEFUN
MY-PACKAGE 5 > (defun)
:MY-DEFUN-RETURNS
MY-PACKAGE 6 > (export 'defun)
T
答案 1 :(得分:2)
您需要阅读有关packages and symbols的更多信息。在这里,我将在需要时对所有符号进行限定,以确保我在谈论哪个符号没有歧义。
您无法重新定义CL:DEFUN
,这将引发未定义的行为,并且您可能通过使其不可用而“破坏”您的运行时。这就是SBCL对软件包使用 locks 的原因,这是一种避免错误地修改软件包及其绑定的方法(您仍然可以解锁软件包,通常不需要这样做)。
在宏的作用域内,您可以根据需要随意解释CL:DEFUN
,这就是Parenscript通过将实际Lisp代码的子集转换为Javascript来实现的。
在任何其他软件包P
中,可以将P:DEFUN
定义为与CL:DEFUN
完全不同的变量/函数/宏/。您可以导出它,一切都很好,可以根据需要使用P:DEFUN
和CL:DEFUN
。
如果您想编写不合格的DEFUN
符号并让读者找出正在引用的符号,则可能发生冲突。通常,库的用户可能会这样定义一个包:
(defpackage :foo (:use :cl :p))
这会导致冲突,因为“ CL”和“ P”软件包均导出“ DEFUN”。解决该问题的一种方法是定义重新绑定DEFUN
并从“ CL”中重新导出所有其他符号的Common Lisp方言。然后,您的用户必须仅使用您的软件包,而不能使用CL软件包。另一种方法是仅使用P中的“ DEFUN”来使用 CL和 shadow-import ,这样DEFUN
是P:DEFUN
的别名(因此,您需要编写CL:DEFUN
来显式引用Common Lisp宏。
上面给出的链接有更多详细信息。