I would like to define a macro named "defun" from within a package i am creating and i would like to export it to be used in certain places. There is a library called parenscript that does this in it's package like so,
(export #:defun)
When i try to do this within my own package i get this SBCL error
Lock on package COMMON-LISP violated when defining DEFUN as a macro while in package COMMON-LISP-USER.
How is this done in the parenscript library? I know that you can type the form;
(ps (defun function-name (args) (body)))
I want to be able to do the same but cannot figure out how this is done?
You want to shadow the original symbol from the CL package.
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
You need to read more about packages and symbols. Here I am going to qualify all symbols when needed so that there is no ambiguity about which one I am talking about.
You cannot redefine CL:DEFUN
, this invokes undefined behavior and you are likely to "break" your runtime by making it unusable. That's why SBCL has a concept of locks for packages, which are a way to avoid modifying a package and its bindings by mistake (you can still unlock a package, by you usually don't need to).
Under the scope of your macro, you are free to interpret CL:DEFUN
as you wish, which is what Parenscript does by translating a subset of actual Lisp code to Javascript.
In any other package P
, you can define P:DEFUN
as a variable/function/macro/whatever that is entirely distinct from CL:DEFUN
. You can export it and everything is fine, you can use both P:DEFUN
and CL:DEFUN
however you want.
Conflicts can happen if you want to write an unqualified DEFUN
symbol and have the reader find out which symbols is being referenced. Typically, users of a library might define a package like so:
(defpackage :foo (:use :cl :p))
This leads to a conflict, because both the "CL" and the "P" packages export "DEFUN". One way to solve that is to define a Common Lisp dialect that rebind DEFUN
and re-exports all other symbols from "CL". Your users must then use only your package and not the CL one. Another way is to use CL and shadow-import only "DEFUN" from P, so that DEFUN
is an alias for P:DEFUN
(consequently, you need to write CL:DEFUN
to explicitly reference the Common Lisp macro).
The link given above goes into more details.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With