覆盖包中的“ defun”

时间:2019-06-02 15:57:15

标签: package lisp common-lisp symbols parenscript

我想在我正在创建的程序包中定义一个名为“ 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)))

我希望能够做到这一点,但无法弄清楚该怎么做?

2 个答案:

答案 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的更多信息。在这里,我将在需要时对所有符号进行限定,以确保我在谈论哪个符号没有歧义。

  1. 您无法重新定义CL:DEFUN,这将引发未定义的行为,并且您可能通过使其不可用而“破坏”您的运行时。这就是SBCL对软件包使用 locks 的原因,这是一种避免错误地修改软件包及其绑定的方法(您仍然可以解锁软件包,通常不需要这样做)。

  2. 在宏的作用域内,您可以根据需要随意解释CL:DEFUN,这就是Parenscript通过将实际Lisp代码的子集转换为Javascript来实现的。

  3. 在任何其他软件包P中,可以将P:DEFUN定义为与CL:DEFUN完全不同的变量/函数/宏/。您可以导出它,一切都很好,可以根据需要使用P:DEFUNCL:DEFUN

  4. 如果您想编写不合格的DEFUN符号并让读者找出正在引用的符号,则可能发生冲突。通常,库的用户可能会这样定义一个包:

    (defpackage :foo (:use :cl :p))
    

    这会导致冲突,因为“ CL”和“ P”软件包均导出“ DEFUN”。解决该问题的一种方法是定义重新绑定DEFUN并从“ CL”中重新导出所有其他符号的Common Lisp方言。然后,您的用户必须仅使用您的软件包,而不能使用CL软件包。另一种方法是仅使用P中的“ DEFUN”来使用 CL和 shadow-import ,这样DEFUNP:DEFUN的别名(因此,您需要编写CL:DEFUN来显式引用Common Lisp宏。

上面给出的链接有更多详细信息。