Apparently, the issue is that after evaluating an (in-package "blah")
form, the symbols from outside that package are no longer available.
This simple sequence fails:
(defpackage "FOO")
(in-package "FOO")
(format t "Hello, world!~%")
; in: COMMON-LISP:LAMBDA COMMON-LISP:NIL
; FOO::FORMAT
;
; caught COMMON-LISP:STYLE-WARNING:
; undefined function: FORMAT
I could import the common-lisp[-usr] package, but since no such
package exists in e.g. gcl, I have to protect it somehow, which is
difficult when the system can't even find IF or COND without package
qualification.
As I said, I'm sure it must be something basic. Thanks in advance for
any help.
You need to add (:use :common-lisp) or equivalent to your package
definition. SBCL is pedantic, which is a "Good Thing".
> OK, I have a CL library that I'm testing in a variety of
> implementations. It works fine in CLISP and GCL, but blows up in
> SBCL. I must be missing something very basic, so if anyone could
> supply guidance, I would appreciate it.
>
> Apparently, the issue is that after evaluating an (in-package "blah")
> form, the symbols from outside that package are no longer available.
> This simple sequence fails:
>
> (defpackage "FOO")
You could (should?) use the :use parameter to defpackage to
list a set of packages to import from... the default for :use for
defpackage (and make-package) is system-dependent.
gcl may still use the pre-ansi names :cl and :cl-user instead
of :common-lisp and :common-lisp-user. If so, you could use reader
conditionals to choose which packages to include:
(defpackage :foo (:use #+ansi :common-lisp #-ansi :cl) ...)
--- or something like that.
> OK, I have a CL library that I'm testing in a variety of
> implementations. It works fine in CLISP and GCL, but blows up in
> SBCL. I must be missing something very basic, so if anyone could
> supply guidance, I would appreciate it.
>
> Apparently, the issue is that after evaluating an (in-package "blah")
> form, the symbols from outside that package are no longer available.
> This simple sequence fails:
>
> (defpackage "FOO")
> (in-package "FOO")
> (format t "Hello, world!~%")
The problem is that DEFPACKAGE with no specific :USE list will end up
using an implementation-defined list of packages. SBCL's
implementation-defined list is empty; other Lisp implementations use
different defaults. For example, here's the result of evaluating
"(package-use-list (make-package (gensym)))" in several
implementations:
CLISP:
=> (#<PACKAGE COMMON-LISP>)
LispWorks Linux 5.0.1:
=> (#<The COMMON-LISP package, 3/4 internal, 978/1024 external>
#<The HARLEQUIN-COMMON-LISP package, 0/4 internal,
225/256 external>
#<The LISPWORKS package, 56/64 internal, 199/256 external>)
Allegro CL 8.0:
=> (#<The COMMON-LISP package>)
SBCL:
=> NIL
OpenMCL 1.0:
=> (#<Package "CCL"> #<Package "COMMON-LISP">)
As you can see, to get predictable results across implementations with
DEFPACKAGE, you really have to specify *some* :USE list, even if it's
empty.
>
> ; in: COMMON-LISP:LAMBDA COMMON-LISP:NIL
> ; FOO::FORMAT
> ;
> ; caught COMMON-LISP:STYLE-WARNING:
> ; undefined function: FORMAT
>
> I could import the common-lisp[-usr] package, but since no such
> package exists in e.g. gcl, I have to protect it somehow, which is
> difficult when the system can't even find IF or COND without package
> qualification.
I don't know much about GCL, but I think there's a way to start it so
it's more conformant with the Common Lisp standard. COMMON-LISP is a
standard package.
Zach
> gcl may still use the pre-ansi names :cl and :cl-user instead
> of :common-lisp and :common-lisp-user. If so, you could use reader
> conditionals to choose which packages to include:
COMMON-LISP and COMMON-LISP-USER are nicknamed to CL and CL-USER
respectively, so using those names is safe. See Section 11.1.2:
http://www.lispworks.com/documentation/HyperSpec/Body/11_ab.htm
Cheers,
Maciej
> I could import the common-lisp[-usr] package,
Package COMMON-LISP-USER (a.k.a. CL-USER) has an "E" in its name.
It's not a Unix thing.
Package CL-USER has no defined exports, so you probably won't get much
mileage out of importing it unless the system has decided to add exports
of its own choosing just to confuse you.
> but since no such
> package exists in e.g. gcl, I have to protect it somehow,
Use package LISP if you want to inherit functionality defined by CLtL.
I'm guessing:
(:use #+ANSI-CL "CL"
#-ANSI-CL "LISP")
is going to suit your needs best, though I don't have GCL around to try
to see whether it uses the LISP package or the "CL" package.
Then again, I'm surprised there's a DEFPACKAGE. You might need to do
#+ANSI-CL
(defpackage "FOO" (:use "CL"))
#+ANSI-CL
(in-package "FOO")
#-ANSI-CL
(in-package "FOO" :use "LISP")
Btw, I think you can do the previous 4 lines in a combined single
expression if you're feeling super-macho...
(in-package "FOO" . #+ANSI-CL () #-ANSI-CL (:use "LISP"))
No, I didn't try any of this. Caveat emptor.
I know; that was just a typo.
> Then again, I'm surprised there's a DEFPACKAGE. You might need to do
> #+ANSI-CL
> (defpackage "FOO" (:use "CL"))
No, GCL groks the standard package system. It just doesn't seem to
have the ANSI standard packages (despite its info file to the
contrary). What the standard calls COMMON-LISP, it calls just LISP.
Thanks to everyone who responded about :use.
Do you know that the default startup mode for GCL is Cltl2?
You need to specify ANSI om the command line to get better Common Lisp
compatibility.
(Dont know if you have done this or if it helps.)
--------------
John Thingstad
I recall trying both modes, and the list of packages was the same, but
I may not have been specifying ANSI mode correctly (I tried gcl --ansi
and gcl -ansi). I'm not in front of my GCL system at the moment so I
can't re-check.
<501 me bash gnulou:~/dev/lisp/palindrome>gcl
GCL (GNU Common Lisp) 2.6.7 CLtL1 Oct 29 2006 02:32:45
Source License: LGPL(gcl,gmp), GPL(unexec,bfd,xgcl)
Binary License: GPL due to GPL'ed components: (XGCL READLINE BFD UNEXEC)
Modifications of this banner must retain notice of a compatible license
Dedicated to the memory of W. Schelter
Use (help) to get some basic information on how to use GCL.
Temporary directory for compiler files set to /tmp/
>(defpackage "FOO" (:use #-gcl :common-lisp #+gcl "LISP"))
#<"FOO" package>
>(in-package "FOO")
#<"FOO" package>
FOO>(format t "Hello, world!~%")
Hello, world!
NIL
FOO>
> No, GCL groks the standard package system. It just doesn't seem to
> have the ANSI standard packages (despite its info file to the
> contrary). What the standard calls COMMON-LISP, it calls just LISP.
Sounds like you've got it under control. But here's one final note to
stir things up:
If there is no COMMON-LISP package, but has the right symbols, you might
see if it lets you do RENAME-PACKAGE to set the names the way you like.
Safest is probably to just rename it to whatever name GCL likes, and then
make sure in the rename call to mention nicknames of all existing nicknames
plus "COMMON-LISP" and "CL" added.
If that doesn't work, there may be something similar you can do. Such
foothold stuff is often painful and may violate the standard, but
often one does it to establish a basic level playing field that makes
other packages you have work better than having to have every instance
of this discover and fix the problem.
A bit of confusion on my part, there... I mean :lisp and
:lisp-user vs :common-lisp and :common-lisp-user.
Also, remember that packages can have nicknames, so even if you start in
ANSI mode, it may be the case that GCL keeps "LISP" as one of the names
or nicknames of the "COMMON-LISP" package. That would make at least
some sense from the point of view of trying to simplify moving old code
to the newer, ANSI system.
To get a good idea, you probably want to do something like
(dolist (p (list-all-packages))
(format t "~A: ~S ~S~%"
p (package-name p) (package-nicknames p)))
--
Thomas A. Russ, USC/Information Sciences Institute
Man CL is so cool! I tried looking into modifying packages a while
back, to add my own nicknames to packages. I had not heard of
RENAME-PACKAGE until now.
This is an idea that was mentioned on c.l.l a while back -- library
creators cannot give concise nicknames that are guaranteed to be
unique since they don't control where their packages will be
used. Nicknames should really be under user control. RENAME-PACKAGE
gives us that through its optional argument. Muahahaha...
(defun package-add-nickname (package nickname)
(rename-package package package ;; not renaming
(cons nickname
(package-nicknames package))))
> (defun package-add-nickname (package nickname)
> (rename-package package package ;; not renaming
> (cons nickname
> (package-nicknames package))))
More or less.
Instead of the call to CONS, you probably want
(adjoin nickname (package-nicknames package) :test #'string=)
to handle duplicates correctly, noting that the nicknames might be strings
or symbols and string= will manage that. You definitely don't want the
default test of #'eql with this call to adjoin.