This is an addendum to the other answer. The other answer explains the difference between lisp-1s (lisps which have a single namespace for function and variable bindings) and lisp-2s (lisps which have a separate namespace for function bindings).
I want to explain why a lisp-2 might make things better, and especially why it did so historically.
First of all let's consider a little bit of Scheme code:
(define (foo x)
(let ([car (car x)])
... in here (car ...) is probably not going to get the car
(bar car)))
(define (bar thing)
... but in here, car is what you expect ...)
So, in foo
I have bound car
to the car of the argument. That's probably terrible style in Scheme, and it means that, in the body of that binding, car
probably does not do what you expect when used as a function. But this problem only matters within the lexical scope of the binding of car
: it doesn't matter within bar
for instance.
Now, in Common Lisp, I can write equivalent code:
(defun foo (x)
(let ((car (car x)))
... (car ...) is fine in here ...
(bar car)))
(defun bar (thing)
... and here ...)
So this is a little bit better, perhaps: within the body of the binding of car
it's still fine to use car
as a function, and indeed the compiler can make very strong assumptions that car
is the function defined by the language and CL has wording in the standard which ensures that this is always true.
And this means that, stylistically, in CL, something like this is probably OK. IN particular I often do things like:
(defmethod manipulate-thing ((thing cons))
(destructuring-bind (car . cdr) thing
...use car & cdr...))
And I think this is fine: in Scheme the equivalent would be horrible.
So that's one reason why a lisp-2 is quite convenient. However there's a much stronger one which doesn't apply to CL but does apply to elisp.
Consider, in elisp, this code:
(defun foo (x)
(let ((car (car x))
(cdr (cdr x)))
(bar car cdr)))
(defun bar (thing-1 thing-2)
...)
Now there's a critical thing to know about elisp: by default it is dynamically-scoped. What that means, is that, when bar
is called from foo
, the bindings of car
and car
are visible in bar
.
So for instance if I redefine bar
as:
(defun bar (thing-1 thing-2)
(cons cdr thing-1))
Then:
ELISP> (foo '(1 . 2))
(2 . 1)
So, now, think of what would happen if elisp was a lisp-1: any function called from foo
will find that (car x)
does not do what it expects! This is a disaster: it means that if I bind the name of a function – any function, including functions I might not know exist – as a variable, then any code in the dynamic scope of that binding will not do what it should.
So, for a Lisp with dynamic scope, as elisp historically had and still does have by default, being a lisp-1 was a disaster. Well, historically, very many lisp implementations did have dynamic scope (at least in interpreted code: it was common for compiled code to have different scoping rules, and scoping rules were often somewhat incoherent in general). So for those implementations, being a lisp-2 was a really significant advantage. And, of course, once a lot of code which assumed lisp-2-ness existed, it was much easier for languages which aimed at compatibility, such as CL, to remain lisp-2s, even though the advantages in a lexically-scoped language are less clear.
As a note: I have used a lisp, long ago, which was both dynamically-scoped (in the interpreter at least?) and a lisp-1. And I had at least one very bad experience (I think involving needing to hard-reset a multiuser machine which had become catatonic because it was paging so much, which made me unpopular with all the other users) as a result of that.