Can anyone here defend Lisp-2? Any time I read about it I seem to instinctively recoil in disgust. To me, the hygiene argument doesn't make up for the extra characters and loss of generality.
What I took away from it was that macros get more tricky to write when you have possible variable capture for functions, which we humans seem to be a little more blind to than for values.
Item 18 contains the compatibility concerns for existing code, which the guys writing the standard seemed to think critical to keep the various vendors on board.
Lisp-2 is much saner. What it adds is just funcall, and it's not such a big deal in practice, because most of the times in the situations of higher-order function you would use apply, reduce or map, which likewise should be used in Lisp-1. What it brings instead is that you have to worry about name clashes much much less. The classic is list vs lst.
What I personally like is that you always know what are you referring to in a higher-order function call: a variable name or a function name. So it just removes the need for some additional intellectual effort of remembering this (i.e. #' is a nice annotation)
Interestingly, the Ur-Lisp (Lisp 1.5) actually had both. There were two ways to define a function. There was one form, LABEL (the ancestor of CL's LABELS), which bound a function like a variable, and another form, DEFINE, that put the function on the symbol's property list. APPLY would check the property list first, then look for a variable binding.
From the Lisp 1.5 manual (1962):
"In actual practice, LABEL is seldom used. It is usually more convenient to attach the name to the definition in a uniform manner... The fact that most functions are constants defined by the programmer, and not variables that are modified by the program, is not due to any weakness of the system. On the contrary, it indicates a richness of the system which we do not know how to exploit very well."
I find the reasoning specious. In particular, files and programs are the same in MS-DOS and Unix. You can, for instance, ls the ls command or cat the cat command. He's also completely ignoring the superiority of the file system's namespacing (by directory) to just having two global buckets like in elisp.
The execute bit comparison is especially specious. If I try to execute a non-executable file, it fails. It doesn't go look for an executable file with the same name. Same as if I try to invoke 0 in Clojure. e.g. (0)
He's right that the symbol resolution of the first entry has different rules but ignores the fact that the shell isn't very good at higher order commands. Which is probably okay for a shell but not much use for a modern programming language.
Finally, he's right that multiple namespaces are a good idea, but that's Accepted Truth these days. It's just that we think namespacing should be under the control of the dev, not dependent on the type of the variable.
you can simply cat cat or ls ls by cd-ing to /bin first... with the caveat that some distros have moved them to /usr/bin or somewhere, hence the 'which'
Exactly. File systems resemble modern namespaces, not namespacing by type. You can put an executable and a data file in the same directory, or not. Your choice.
I have much the same reaction. My theory is that it comes from an extinct Lisp tribe. Those who think like that these days use different languages (Java?). We can only really hunt for someone who dates from that time and remembers what they were thinking. Maybe Richard Stallman? :)
I've used both Lisp-1 and Lisp-2, and really, this is a tempest in a teapot. It makes zero difference to how I think about code and very little difference to how I write it.
The paper that coined the term http://www.nhplace.com/kent/Papers/Technical-Issues.html lists arguments on both sides. IIRC the main argument in favour of Lisp-2 is that it makes CL-style macros easier to write by making it easier to avoid some kinds of variable capture.
Perhaps that was worded wrong, but what I meant was the idea that you have names that map to things, and that you have an evaluation order for those things. So that if you see
(foo a b c) and it isn't quoted, we know that foo will be resolved and evaluated, so will a, b, and c, and then the objects to which a, b, and c resolved will be applied to the object to which foo was resolved.
So, if I then type (a foo b c), we get the same behavior with different object resolutions.
Hmm...one symbol that points to both values and methods...maybe that could be the foundation upon which some types of useful abstractions could be built...nah, it would never be successful.