Suppressing Symbol Package Prefixes (Common Lisp) - package

When printing out object names which are interned in one package, but referenced from another package, the print name will include the full package name. For example, the following interaction interns the symbol X in PKG1, and prints its value from CL-USER:
* *package*
#<PACKAGE "COMMON-LISP-USER">
* (defpackage :pkg1 (:use :cl))
#<PACKAGE "PKG1">
* (in-package :pkg1)
#<PACKAGE "PKG1">
* (defvar x '(a b c))
X
* (in-package :cl-user)
#<PACKAGE "COMMON-LISP-USER">
* pkg1::x
(PKG1::A PKG1::B PKG1::C)
Sometimes for diagnostic/debugging reasons, I would like to printout external symbols without their package prefixes. In this case the printout would then look like (A B C). For complicated or nested objects where you know what the names mean, the package prefixes can make the printout hard to read, especially if there are multiple packages. Can the prefixes be temporarily suppressed for printout?

No, but you can elide the prefixes of one package by temporarily binding *package* to it for the printout.
Example:
(let ((*package* (find-package :pkg1)))
(print pkg1:*x*))
Since *package* is globally dynamic, this affects everything called inside (i. e. in the dynamic extent of its invocation) this let form but doesn't affect anything outside.

Related

:EXPORT from Package in Common Lisp

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

Common Lisp appending package name to quoted keys in macros

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 ...

Use package shadowing symbols

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.

Changing hunchentoot's current package

I've set up a hunchentoot project with quickproject per Xach's instructions. In-package is run at the top of the file, and hunchentoot is started later in the file. The REPL is switched to my package also, but it is evident that hunchentoot is not running in my package. This causes some disparity between tests in the REPL and the browser. For example there is a function that looks up some stuff in an alist, but hunchentoot gets NILs from it because it is using symbols from another package.
I am aware from the answers to this related question that I can wrap every piece of code that interns symbols in something like
(let ((*package* (find-package :package-name)))
...)
which will set the *package* var to the correct package for the duration of the enclosed code.
Putting this in every function that needs it feels to me like a messy hack.
Intuition says that I should be able to start hunchentoot like this:
(let ((*package* (find-package :package-name)))
(hunchentoot:start (make-instance 'hunchentoot:easy-acceptor :port 4242)))
So that it makes its whole run with *package* set to the value that I prefer, thereby ensuring that any interning done by a call from the webserver is done in my package. It doesn't work. Hunchentoot ends up interning things under cl-user, possibly due to using a macro like WITH-STANDARD-IO-SYNTAX as in the link above.
Even if I can persuade hunchentoot to do what I want, is there a reason why my 'messy hack' is still the better thing to do?
This is not a Hunchentoot specific question, but relates to Common Lisp packages in general.
What you are seeing is that in your code, the *PACKAGE* special variable is not bound to your own package. IN-PACKAGE changes *PACKAGE* only at compile and read time. When a function in your package is called at run time, *PACKAGE* is not re-bound and needs to be bound explicitly.
When you are using INTERN or FIND-SYMBOL, it is often best to specify the package as argument. Alternatively, you can bind *PACKAGE* yourself.
Try LOADing this file to see:
(defpackage :foo
(:use :cl))
(in-package :foo)
(defun test ()
(print *package*))
(in-package :cl-user)
(foo::test)
Common Lisp code does not 'run' in a package.
There are a few operations which use a default package. Like reading a symbol from a text stream:
CL-USER 1 > *package*
#<The COMMON-LISP-USER package, 56/64 internal, 0/4 external>
CL-USER 2 > (read-from-string "FOO")
FOO
3
CL-USER 3 > (describe (read-from-string "FOO"))
FOO is a SYMBOL
NAME "FOO"
VALUE #<unbound value>
FUNCTION #<unbound function>
PLIST NIL
PACKAGE #<The COMMON-LISP-USER package, 57/64 internal, 0/4 external>
or like finding a symbol:
(find-symbol "FOO")
These operations depend on the value of the variable cl:*package*.
To make sure that these operations (reading symbols, finding symbols, interning symbols, ...) are doing what you expect, you may want to:
set or bind the *package* variable to the package you want to
explicitly pass the package to operations. You can call (find-symbol "FOO") and have *package* set to some package. But you can also call (find-symbol "FOO" my-package) by passing the respective package as an argument.
Summary: Common Lisp code does not 'run in a package', but it uses the variable *package* as a default package for package-related operations. You need to set or bind this variable when you use this mechanism.
When Hunchentoot runs in multi-threaded, its acceptors and handlers are processed in child threads made with bordeaux-threads on non-Lispwork CL implementation. The reason of the situation you asked is that the current packages of child threads become COMMON-LISP-USER.
To get the result you want, you can make child threads' current packages same as calling thread's with implementing START-THREAD generic function corresponding to ONE-THREAD-PER-CONNECTION-TASKMASTER taskmaster.
Note that you use latest Hunchentoot which has START-THREAD generic function, I use of version 1.2.19.
(in-package :hunchentoot)
(defmethod start-thread ((taskmaster one-thread-per-connection-taskmaster) thunk &key name)
(let* (;; calling thread's current package
(package-name (package-name *package*))
;; initial special bindings passed to bordeaux threads
(initial-bindings `((*package* . (find-package ,package-name)))))
;; making child thread passing initial special bindings
(bt:make-thread thunk :name name :initial-bindings initial-bindings)))

CLisp: "use-package" resolving conflicts non-interactively

I'm trying to use parenscript in GNU common lisp to compile a lisp file into a javascript one.
I find that using the PS symbol macro "#" doesn't work if I try to use its prefix ("ps:#"). However, if I use the REPL and run (use-package :ps) before I try compiling the lisp file, everything works as expected (and I don't have to use the prefixes).
The problem is that the PS package contains clashing symbols, e.g:
*** - (USE-PACKAGE (#<PACKAGE PARENSCRIPT>) #<PACKAGE COMMON-LISP-USER>): 2 name conflicts remain
Which symbol with name "CHAIN" should be accessible in #<PACKAGE COMMON-LISP-USER>?
The following restarts are available:
PARENSCRIPT :R1 #<PACKAGE PARENSCRIPT>
COMMON-LISP-USER :R2 #<PACKAGE COMMON-LISP-USER>
ABORT :R3 Abort main loop
I can resolve this interactively by choosing :r1, but when I try to put this step in my script it just bails (since it's non-interactive, it doesn't give me a choice of what restart to use)
I'd love to say (in my script) "just use the PS version of all clashing symbols", but I can't figure out how to do so.
It would also be okay if I could say (as one might in python), "from PS import chain, #, (etc)" - specifying each symbol I want to import manually.
Instead of working in the COMMON-LISP-USER package, make your own with DEFPACKAGE:
(defpackage #:my-awesome-program
(:use #:cl #:parenscript))
(in-package #:my-awesome-program)
; your code here
COMMON-LISP-USER might include all sorts of implementation-specific symbols.
You can also use SHADOWING-IMPORT to get individual symbols, overriding what might already be currently visible in the package, e.g.
(shadowing-import 'ps:*)

Resources