opening it up with Common Lisp

Favorite weblogs

Lisp Related

Bill Clementson

Finding Lisp


Planet Lisp



Talking Points Memo

This Modern World

Working for Change

Other home


Recent Readings

Book review: Darwinia
Reviewed: Friday, August 11, 2006

Summer reading: Spin
Reviewed: Saturday, August 5, 2006

Reviewed: Tuesday, July 18, 2006

the Omnivoire's Delimma
Reviewed: Wednesday, July 12, 2006

the Golem's Eye
Reviewed: Wednesday, May 31, 2006


In which we learn more about in-package
Thursday, May 11, 2006

Back when I was learning Lisp, I typed (in-package :foo) or (in-package "FOO"). Then one day my mentor told me that in-package was a macro so just typing (in-package foo) was fine. Was he right?

If he was talking only about the Listener, then I’d say that he was. If, on the other hand, he had been talking about using the bare version of in-package in files that are compiled, he was not. Yesterday, a #lisp discussion revealed to me the error of my ways (or, at least, one error). It is correct that in-package is a macro and that the Lisp package machinery will find the correct package and place you in that package when it encounters (in-package foo). At issue is what the “foo” signifies and that depends on the current state of your Lisp when the in-package is reached. If you are in package bar then “foo” will signify bar::foo ; if you are in package goo then “foo” will signify goo:foo. If the symbol “foo” is not yet interned in the current package, then Lisp will create it and intern it there. All of this sounds reasonable enough so aside from namespace pollution, what is the problem?

Suppose you working on a system with multiple packages. Suppose that you are in package foo and working on a file named “qurp.lisp” in package bar and that the natural order of these packages is that package foo does not exist when this “qurp” is loaded into a fresh Lisp. Now imagine what happens if you recompile the system… well, “qurp” has been modified so it will get recompiled. The Lisp compiler will look at the (in-package bar) that occurs on the first line of the file and see (in-package foo::bar). Remember that foo is the current package and remember that all seems because the package foo exists. Everything, in fact, seems to go swimmingly.

But it hasn’t.

Because when you quit and restart Lisp and try to re-load that system on which you were working, Lisp will try to reload “qurp.fasl” and encounter the symbol foo::bar but the package foo will not have been defined yet (remember, qurp gets loaded before foo is defined) and you’ll get an error and (if you were me) wonder why that happens…

If you’ve followed me, then you’ll now know why it happens and what to do about it: the solution is never to quit Lisp. Ever. Actually, the solution is to always preface the package names in your in-packages with either a “:” or (better yet) a “#:”. The first form puts the package name into the keyword package and that is guaranteed to be available. The second refers to the symbol in no package at all (speaking slightly loosely) and will also never get you into trouble.

I hope that’s clear. I’d say more but I’ve got about 30 more systems on which I need to run this script:

find . -name "*.lisp" \ -and -not -path "*/asdf-systems/*" \ -and -not -path "*/_darcs/*" \ -and -not -path "*/tags/*" \ -exec perl -pi \ -e "s/\(in-package\s+([^:#\"][^)\"]*)/(in-package #:\1/gi" {} \; \ -exec perl -pi \ -e "s/\(in-package\s+\"([^\"]+)\"/(in-package #:\1/gi" {} \; \ -print



Home | About | Quotes | Recent | Archives

Copyright -- Gary Warren King, 2004 - 2006