What is the rationale behind the design decision to have separate namespaces for values and functions in Common Lisp? What are the arguments for and against it?
Please see Richard P. Gabriel's paper Technical Issues of Separation in Function Cells and Value Cells for a full academic treatment of this subject.
I actually like having several namespaces (more than two even); it makes things easier for the user and the compiler-writer (implementation):
CL-USER> (defclass test () ())
#<STANDARD-CLASS TEST>
CL-USER> (defun test ())
TEST
CL-USER> (defparameter test 42)
TEST
CL-USER> (describe 'test)
COMMON-LISP-USER::TEST
[symbol]
TEST names a special variable:
Value: 42
TEST names a compiled function:
Lambda-list: ()
Derived type: (FUNCTION NIL (VALUES NULL &OPTIONAL))
Source form:
(LAMBDA ()
(DECLARE (MUFFLE-CONDITIONS COMPILER-NOTE))
(PROGN
(SB-INT:NAMED-LAMBDA TEST
NIL
(BLOCK TEST))))
TEST names the standard-class #<STANDARD-CLASS TEST>:
Direct superclasses: STANDARD-OBJECT
No subclasses.
Not yet finalized.
No direct slots.
; No value
CL-USER> (make-instance 'test)
#<TEST {1005B1D601}>
CL-USER> (test)
NIL
CL-USER> test
42
CL-USER>
Though there may be plenty of arguments each way in theory, I'd bet that it is largely philosophical in origin. Scheme, a Lisp-1, prefers elegance over practicality, and chose the same define
syntax for variables and functions, which makes a single namespace feel natural (and encourages a functional style of programming). Common Lisp tends to prefer practicality and power over elegance, and was an attempt at consensus-building, so seeing an existing two-namespace solution broadly accepted and working well, accepted it.
In practice, however, it mostly means three things:
- In Common Lisp (and other Lisp-2's), you have to use
funcall
a lot - In Scheme (and other Lisp-1's), you have to be careful not to override
needed function names with variables; e.g. function arguments like
lst
instead oflist
- On the Internet, there will be arguments
It is one major factor in why some people prefer one Lisp to another, however.
Common Lisp is basically a descendant from the original Lisp 1.5, or rather, a unification of its diverging dialects. The original Lisp 1.5 was what is nowadays called a Lisp-2. Because it was back in the sixties and the fact that you could pass functions to other functions was weird enough. No one would even think of letting them share the same namespace. Almost any language invented today with support for higher order functions and anonymous functions chooses the single-namespace approach. Including Clojure, which is otherwise closer to Common Lisp than to Scheme.
Scheme, like Clojure, wasn't originally a divergent dialect from Lisp 1.5, and for their purposes it makes sense.
Of course, in Clojure, vectors, hash maps, sets and all that can also be applied to arguments, so in a sense a vector in Clojure could be seen as a function that takes a natural number and produces a value from that.