| kyle_burton ( @ 2008-03-10 20:57:00 |
| Entry tags: | lisp |
Keyword symbols vs non-keyword symbols
It took too long for it to really click so while I'm thinking about this
again I'm writing it down. There are good
reasons why you should avoid using symbols of the form 'foo in
preference to :foo. The main semantic difference is that the one
preceded with a single quote is tied to the package where it occurrs, while the
one preceded by the colon is placed within the keyword package.
What this means to you and your code may vary. One immediate reason to use
keyword symbols (the ones that start with a colon) is that they are the same
everywhere - they are equal (eq even). This means
that they're shared - if you take symbols as arguments, or return symbols as
values, then the keyword symbols will be easier to use. You won't have to
export them from your package for them to be accessible (except in very rare,
unhygenic, cases, eg: aif).
CL-USER> (defpackage :foo
(:use :common-lisp)
(:export :qux))
#<PACKAGE "FOO">
CL-USER> (in-package :foo)
#<PACKAGE "FOO">
FOO> (defun qux ()
'bar)
QUX
FOO> (equal 'bar (qux))
T
FOO> (in-package :cl-user)
#<PACKAGE "COMMON-LISP">
CL-USER> (equal 'bar (foo:qux))
NIL
CL-USER>
That last one there was somehow confusing to me for a long time. Using keyword symbols solves that issue neatly:
CL-USER> (defpackage :foo (:use :common-lisp) (:export :qux)) #<PACKAGE "FOO"> CL-USER> (in-package :foo) #<PACKAGE "FOO"> FOO> (defun qux () :bar) STYLE-WARNING: redefining QUX in DEFUN QUX FOO> (equal :bar (qux)) T FOO> (in-package :cl-user) #<PACKAGE "COMMON-LISP"> CL-USER> (equal :bar (foo:qux)) T CL-USER>
The other reason to use them is that they're not just interned for the package they were defined in, but all keyword symbols are interned in the keyword package - saving memory in your running instance.
This point was lost on me until I started using packages seriously. I had no context for understanding it until I started using packages to organize my code.
In general you should probably be using keyword symbols as your default.