I'm aware that Common Lisp has different binding environments for functions and variables, but I believe that it also has another binding environment for tagbody labels. Are there even more binding environments than this? If so, then is it fair to categorize Common Lisp as a Lisp-2?
These question are not meant as pedantry or bike-shedding, I only want to gain a better understanding of Common Lisp and hopefully get some pointers into where to dig deeper into its spec.
I'm aware that Common Lisp has different binding environments for
functions and variables,
That would be namespaces, according to the HyperSpec:
namespace n. 1. bindings whose denotations are restricted to a
particular kind. The bindings of names to tags is the tag
namespace.'' 2. any mapping whose domain is a set of names.
A
package defines a namespace.''
(Point 1.)
but I believe that it also has another binding environment for tagbody
labels. Are there even more binding environments than this?
Yes, there are more namespaces. I even remember a little snippet exposing most of them, but unfortunately, I can't find it anymore¹. It at least exposed variable, function, tag, and block namespaces, but maybe also types and declarations were included. There is also another SO answer that lists these namespaces.
If so, then is it fair to categorize Common Lisp as a Lisp-2?
In the comments to the above linked answer, Rainer Joswig agrees that the "general debate is about Lisp-1 against Lisp-n".
The "2" might be due to the relative importance of the distinction between value and function slots, or because the objects of the other namespaces aren't first-class objects. For example in the Gabriel/Pitman paper referenced in the other answer:
There is really a larger number of namespaces than just the two that
are discussed here. As we noted earlier, other namespaces include at
least those of blocks and tags; type names and declaration names are
often considered namespaces. Thus, the names Lisp1 and Lisp2, which we
have been using are misleading. The names Lisp5 and Lisp6 might be
more appropriate.
and:
In this paper, there are two namespaces of concern, which we
shall term the "value namespace" and the "function namespace." Other
namespaces include tag names (used by TAGBODY and GO) and block names
(used by BLOCK and RETURN-FROM), but the objects in the location parts
of their bindings are not first-class Lisp objects.
¹) PAIP, p. 837:
(defun f (f)
(block f
(tagbody
f (catch 'f
(if (typep f 'f)
(throw 'f (go f)))
(funcall #'f (get (symbol-value 'f) 'f))))))
In PAIP, Peter Norvig says "Common Lisp has at least seven name spaces" (p. 836).
The seven he lists are:
- functions and macros
- variables
- special variables
- data types
- label for go statements within a tagbody
- a block name for return-from statements within a block
- symbols inside a quoted expression
Peter Seibel makes a great point in his comp.lang.lisp post about "compiler" versus "library" namespaces. I think all of Norvig's seven namespaces are "compiler" namespaces.
See for example this old discussion post from comp.lang.lisp:
http://coding.derkeiler.com/Archive/Lisp/comp.lang.lisp/2004-04/0737.html
Yes - http://www.lispworks.com/documentation/lw51/CLHS/Body/t_symbol.htm#symbol specifies a separate value cell and function cell, consonant with a lisp-2.
There is also a property list, but as there is no context in which a symbol "naturally" refers to its property list, it is not usual to describe CL as a lisp-3 (in fact, I am not aware of any language usually so designated).