I found out that my package has a problem shadowing delete from the common-lisp package. I have tried various types of shadowing, but none of them worked for me. I guess I'm using it wrong, but still can't make it to work.
I have shortened the code just to show the problem part
This solution throws error: Redefining macro DELETE visible from package COMMON-LISP.
(in-package "CL-USER")
(defpackage :simple-db
(:use :common-lisp)
(:shadow :delete)
(:export :delete))
Another solution throws error: Duplicated symbols in "SIMPLE-DB" defpackage: "DELETE".
(in-package "CL-USER")
(defpackage :simple-db
(:use :common-lisp)
(:shadow :delete)
(:export :delete)
(:shadowing-import-from :simple-db :delete))
The problem you are having is probably not in your package definition (the first one is fine), it's in packages which want to use your package, and also to use CL. Those packages end up with references both to CL:DELETE and SIMPLE-DB:DELETE. Given your definition:
(defpackage :simple-db
(:use :common-lisp)
(:shadow :delete)
(:export :delete))
Then any package which wants to use both SIMPLE-DB and CL will get an error.
(defpackage :simple-db-user
;; this is an error
(:use :common-lisp :simple-db))
You will also see this in any package (for instance CL-USER) if you simply say (use-package :simple-db).
The traditional way to resolve this error is use SHADOWING-IMPORT to pick the symbol you want:
(defpackage :simple-db-user
(:use :common-lisp :simple-db)
(:shadowing-import-from :simple-db :delete))
or, in an existing package:
(shadowing-import '(:delete) :simple-db)
There are (I think) nicer solutions which involve defining packages which are 'like' CL but which redefine some symbols, and which you then treat like a mutant CL package, but those solutions require macrology to make them easy to use which I won't give here.
I don't see a problem:
* (cl:defpackage :simple-db
(:use :common-lisp)
(:shadow :delete)
(:export :delete))
#<PACKAGE "SIMPLE-DB">
* (defun simple-db:delete (foo) foo)
SIMPLE-DB:DELETE
* (describe 'simple-db:delete)
SIMPLE-DB:DELETE
[symbol]
DELETE names a compiled function:
Lambda-list: (FOO)
Derived type: (FUNCTION (T) (VALUES T &OPTIONAL))
Source form:
(SB-INT:NAMED-LAMBDA SIMPLE-DB:DELETE
(FOO)
(BLOCK SIMPLE-DB:DELETE FOO))
Related
I have defined a package like the following:
(defpackage :thehilariouspackageofamirteymuri
(:nicknames ampack amir teymuri)
(:use common-lisp)
(:export say-hi-to))
(in-package :amir)
(defun say-hi ()
"Docstring"
"Hello")
(defun say-hi-to (who)
(concatenate 'string (say-hi) " " who " from " (package-name *package*) "!"))
Now changing to the package also the #'say-hi is accessible:
(in-package :amir)
(say-hi) ; -> "Hello"
(say-hi-to "World") ; -> "Hello World from THEHILARIOUSPACKAGEOFAMIRTEYMURI!"
Isn't the export keyword telling to make things external for the package? Why is the non-external #'say-hi also exported?
Since you are using again (in-package :amir) the following forms are evaluated in that package, so that you can use all the function defined in it. To check which definitions are exported, you should switch to a different package.
Let’s try the standard package CL-USER:
AMIR> (in-package :cl-user)
#<Package "COMMON-LISP-USER">
CL-USER> (say-hi)
Undefined function SAY-HI called with arguments ("world") ; as expected, but...
CL-USER> (say-hi-to "world")
Undefined function SAY-HI-TO called with arguments ("world") ; ops!!
CL-USER> (amir:say-hi-to "world)
"Hello world from COMMON-LISP-USER!"
CL-USER> (amir:say-hi)
Reader error: No external symbol named "SAY-HI" in package #<Package "THEHILARIOUSPACKAGEOFAMIRTEYMURI"> .
The reason is that exporting a symbol does not mean that we can use it without qualiyfing its package. As you can see, however, only symbols exported from a packgage can be used with “:”. If you want to use the symbol without the package name as prefix, you must import it before.
So, let’s start again.
CL-USER> (defpackage :another-package (:use :amir))
#<Package "ANOTHER-PACKAGE">
CL-USER> (in-package :another-package)
#<Package "ANOTHER-PACKAGE">
ANOTHER-PACKAGE> (say-hi-to "world")
"Hello world from ANOTHER-PACKAGE!"
ANOTHER-PACKAGE> (say-hi)
Undefined function SAY-HI called with arguments ()
Inside ANOTHER-PACKAGE you can now use the exported symbol without qualifications.
In general, exporting and importing symbols in packages in Common Lisp is not so intuitive, and a good description of all the intricacies of packages can be found at the link cited in the other answer.
Check the difference without changing the current package. You will find more information e.g. here
I noticed the following behavior in Common Lisp (at least using SBCL), which I was able to reduce it to the following:
Suppose I have the following Macro:
(defpackage "MY-TEST"
(:use "COMMON-LISP")
(:export :appended
:not-appended))
(in-package :MY-TEST)
(defmacro not-appended ()
`(list ':type 'array))
(defmacro appended ()
`(list ':type 'something-else))
The following is the output:
* (my-test:not-appended)
(:TYPE ARRAY)
* (my-test:appended)
(:TYPE MY-TEST::SOMETHING-ELSE)
Notice that in the second macro, the namespace is preceding the "SOMETHING-ELSE".
Questions:
Why is t the case that they differ? Honestly I was expecting the behavior of the "not-appended" macro. Is that because "array" is somehow known to Common Lisp?
If yes, then where can I find the other known keywords?
Note that this is fully unrelated to macros and is an effect of packages, symbols and how symbols are printed:
The package `MY-TEST':
CL-USER 2 > (defpackage "MY-TEST"
(:use "COMMON-LISP")
(:export :appended
:not-appended))
#<The MY-TEST package, 0/16 internal, 2/16 external>
Making the package the current package by calling in-package:
CL-USER 3 > (in-package :MY-TEST)
#<The MY-TEST package, 0/16 internal, 2/16 external>
Let's compute a list of the symbols array and foo. See how the REPL prints it as (ARRAY FOO) because both symbols are accessible in package MY-TEST.
MY-TEST 4 > (list 'array 'foo)
(ARRAY FOO)
Making CL-USER the current package:
MY-TEST 5 > (in-package :cl-user)
#<The COMMON-LISP-USER package, 151/256 internal, 0/4 external>
Now let's get the second last value and see how the REPL prints it:
CL-USER 6 > **
(ARRAY MY-TEST::FOO)
ARRAY is printed without package prefix, because it is the same symbol from the package COMMON-LISP (which was used in the package MY-TEST). FOO is printed with the package prefix MY-TEST, because it is an internal symbol in that package - it was interned there, because then the current package was MY-TEST. There are two colons, because the symbol FOO is not exported from the package MY-TEST and it is also not imported into the package CL-USER.
The package "CL" and "CL-USER" contain all the symbols from the programming language Common Lisp - thus importing "CL" into your own package makes all of those symbols available in that package, too.
CL-USER 7 > (let ((l '()))
(do-symbols (sym (find-package "CL") l)
(pushnew sym l)))
(MAKE-ARRAY INVOKE-DEBUGGER STRING-TRIM WILD-PATHNAME-P UNREAD-CHAR RESTART-BIND ...
What is the difference between them in the context of a Common Lisp package? I am reading through SLIME documentation and some commands mention that extensively.
What is the syntax ? The symbols you export are external.
(in-package :cl-user)
(defpackage str
(:use :cl)
(:export
:trim-left
))
(in-package :str)
;; exported: can be accessed with `str:trim-left`.
(defun trim-left (s)
"Remove whitespaces at the beginning of s. "
(string-left-trim *whitespaces* s))
;; forgot to export: can still access it with `str::trim-right`.
(defun trim-right (s)
"Remove whitespaces at the end of s."
(string-right-trim *whitespaces* s))
The author of a Common Lisp package can export a symbol for the user of the package. Then the symbol is an external symbol and you can access it with package-name:external-symbol-name.
Internal symbols are not meant for the user but can be accessed with package-name::symbol-name
More explanations are in Peter Seibel's book and Common Lisp the Language
For instance I have this package definition which shadows COMMON-LISP:LISTEN :
(defpackage :shadows
(:use :common-lisp)
(:shadow #:listen)
(:export #:listen))
And then I want to use this package from another package, say
(defpackage :light
(:use :common-lisp
:shadows))
What is the purpose of shadow if I cannot actually override Common Lisp symbols when using the package ?
Simple
The :shadow argument to defpackage
affects the definition of the package shadows,
not the later use of shadows in light.
You need to use shadowing-import:
(defpackage #:shadows
(:use #:common-lisp)
(:shadow #:listen)
(:export #:listen))
(defpackage #:light
(:shadowing-import-from #:shadows #:listen)
(:use #:common-lisp #:shadows))
(eq 'light::listen 'shadows:listen)
==> T
(describe 'light::listen)
==>
SHADOWS:LISTEN is the symbol SHADOWS:LISTEN, lies in #<PACKAGE SHADOWS>,
is accessible in 2 packages LIGHT, SHADOWS.
#<PACKAGE SHADOWS> is the package named SHADOWS.
It imports the external symbols of 1 package COMMON-LISP and
exports 1 symbol to 1 package LIGHT.
Bulk
If you need to do bulk shadowing, you would need to use individual functions
(make-package,
import,
export,
shadow,
use-package):
(defparameter *my-shadow-list* '(#:car #:cdr))
(make-package '#:my-package :use nil)
(import *my-shadow-list* '#:my-package)
(export *my-shadow-list* '#:my-package)
(shadow *my-shadow-list* '#:my-package)
(use-package '#:cl '#:my-package)
(make-package '#:my-user)
(shadowing-import *my-shadow-list* '#:my-user)
(use-package '(#:cl #:my-package) '#:my-user)
(describe 'my-user::car)
==>
MY-PACKAGE:CAR is the symbol MY-PACKAGE:CAR, lies in #<PACKAGE MY-PACKAGE>,
is accessible in 2 packages MY-PACKAGE, MY-USER.
#<PACKAGE MY-PACKAGE> is the package named MY-PACKAGE.
It imports the external symbols of 1 package COMMON-LISP and
exports 2 symbols to 1 package MY-USER.
You might find macroexpand-1 useful in decising how get where you need to go:
(macroexpand-1 '(defpackage #:light
(:shadowing-import-from #:shadows #:listen)
(:use #:common-lisp #:shadows)))
==>
(EVAL-WHEN (:COMPILE-TOPLEVEL :LOAD-TOPLEVEL :EXECUTE)
(SYSTEM::%IN-PACKAGE "LIGHT" :NICKNAMES 'NIL :USE 'NIL :CASE-SENSITIVE NIL
:CASE-INVERTED NIL)
(SYSTEM::SHADOWING-IMPORT-CERROR "LISTEN" "SHADOWS" NIL "LIGHT")
(USE-PACKAGE '("COMMON-LISP" "SHADOWS") "LIGHT") (FIND-PACKAGE "LIGHT")) ;
T
PS. Shadowing ANSI CL standard names is not a very good idea for your code readability.
OK so there actually is a handy way to do this.
In my many-shadows package I export a shadowing-import-from function. It looks like this :
(defun shadowing-import-from ()
`(:shadowing-import-from :many-shadows
,#(package-shadowing-symbols :many-shadows)))
And then, in the light defpackage I just READ-EVAL it :
(defpackage :light
(:use :common-lisp
:many-shadows)
#.(many-shadows:shadowing-import-from))
So it is explicit that something was shadowed and that I want to use the symbols from many-shadows in priority. And it is short enough to be documented and used pragmatically.
Thank you #sds for pointing me to :shadowing-import-from.
What is the purpose of shadow if I cannot actually override Common Lisp symbols when using the package?
The purpose of a package having a list of shadowing symbols is to resolve conflicts arising from package use by that package. Shadowing has no effect on anything exported.
When a package uses others, conflicts can arise when two or more used packages export a symbol by the same name. Similarly, conflicts can also arise between a used package and symbols in the local package. These conflicts are treated as errors. On a symbol-by-symbol basis, shadowing squelches these conflicts. A symbol, which is present in the package, is added to its list of shadowing symbols. Any conflict is then silently resolved in favor of that symbol.
Being a shadowing symbol doesn't bestow any special powers on a symbol when it is regarded from outside the package where it has that status.
For each package, we have to separately arrange the "visibility stack", including its own shadowing symbols, if necessary.
In Common Lisp package definition, what is the difference between
(defpackage #:foo
(:use :cl)
(:export #:bar
#:baz))
(in-package #:foo)
and
(defpackage :foo
(:use :cl)
(:export :bar
:baz))
(in-package :foo)
I mean. When I have to use the "#" character? All these symbols are uninternerd, right?
:foo is the syntax for a keyword symbol, and #:foo is the syntax for an uninterned symbol. When a symbol is used primarily to get at the string that is its name (as in defpackage and in-package), I prefer to use uninterned symbols.
Here are the other options:
use a keyword symbol; I don't like how this interns keyword symbols that show up in apropos and other places
use a string; I don't like how this gratuitously breaks Allegro's "modern" mode
use a plain symbol; I don't like how this both interns a symbol, and how it interns it in a potentially random package
Which style you or anyone else uses is a matter of taste.