I'm reading Gigamonkey's (Peter Seibel's) Practical Common Lisp, and came across the following statement in the section about DO in the Macros chapter:
As with the variable definitions in a LET, if the init-form is left out, the variable is bound to NIL. Also as with LET, you can use a plain variable name as shorthand for a list containing just the name.
I don't know what he means about "using a plain variable as shortand for a list containing just the name," that is, the second sentence. The first sentence is backed up in the Common-Lisp Hyperspec for LET, and by a simple example like (let (n) n) ~~> NIL
, but I can't find anything that corresponds to the second sentence. In fact, something like (let n n)
horks an SBCL compiler.
What does it mean? What's a minimal example of that use?
It simply means that all three of these have the same effect:
(let ((x nil)) (let ((x)) (let (x)
x) x) x)
In each case, x is bound to nil. Most people are familiar with the first case. The second case doesn't include the init-form, but Common Lisp is defined to bind x to nil in that case too. Of course, the second case, in one way of looking at it, has more parentheses that you need (it's just an extra set of parentheses around the variable), so you can even take another shortcut and just write the variable by itself.
In the documentation for let, we see that the syntax for let is:
let ({var | (var [init-form])}*) declaration* form* ⇒ result*
From that, we see that every use of let will look something like
(let (…) …)
But what goes into that inner list?
{var | (var [init-form])}*
The * means that there can be any number (zero or more) things within that list, and each one either matches var or (var [init-form]). A var is simply a symbol that can be used as a variable. The (var [init-form]) is a list that has a var as the first element, and optionally has a second element, the init-form.
But that means that in two possible cases (the var all by itself, and the list without an init-form) there is no init-form. Rather than having an unbound or uninitialized variable, Common Lisp defines the value in those cases to be nil.
Why is so much variation permitted? A lot of it is for consistency among different special forms in Common Lisp. Have a look at Issue VARIABLE-LIST-ASYMMETRY Writeup. For more about reading the syntax specifications in the documentation, have a look at 1.4.4.20 The “Syntax” Section of a Dictionary Entry.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With