On Wed, 3 Sep 2008 08:22:17 -0500, Alan Watson
<alan at alan-watson.org> wrote:
>See:
>>http://www.nhplace.com/kent/Papers/Technical-Issues.html
Very illuminating!
Ever since my first exposure to both Scheme and Common Lisp in
college, I had never quite understood why I had always had so much
more difficulty in programming in Common Lisp than in Scheme in
solving exercises similar to those that appear in SICP.
At first, I had thought that it was because of namespace collisions in
Common Lisp. But after seeing the above-referenced document, I
realize that the issue was deeper: It actually had to do with the
differentiation between function namespaces and value namespaces, and
the resulting cumbersomeness of writing certain higher-order functions
in Common Lisp.
Specifically, to cite the above-referenced document:
>Lisp2 is slightly more complicated than Lisp1 in situations where we would want to do either of the following:
>> * Fetch the value of an identifier in the value namespace and call it as a function
> * Fetch the value of an identifier in the function namespace and pass it around as a value.
>>To use the value of an identifier in the value namespace as a function, Lisp2 provides this notation:
>> (FUNCALL <identifier> . <arguments>)
>>For example, in Lisp2 one would write
>> (DEFUN MAPC-1 (F L) (DOLIST (X L) (FUNCALL F X)))
>>In Lisp1, one would write
>> (DEFUN MAPC-1 (F L) (DOLIST (X L) (F X)))
I vaguely remember this 'FUNCALL notation and how lack of a good
understanding of how to use this notation at the time caused
difficulties in writing some higher-order functions.
The above-referenced document continues:
>To use the value of an identifier in the function namespace as a normal value, Lisp2 provides this notation:
>> (FUNCTION <identifier>)
>>which is often abbreviated as simply
>> #'<identifier>
>>For example, in Lisp2 one would write
>> (MAPC #'PRINT '(A B C D))
>>In Lisp1, one would write
>> (MAPC PRINT '(A B C D))
Again, I vaguely remember having had difficulties in differentiating
between the 'FUNCTION, 'FUNCALL, '#'', and ''' notations (especially
when sleep-deprived, as I always was).
To continue:
>The differences are more striking in a larger, more complex example. In Lisp2, one can write the Y operator as
>> (DEFUN Y (F)
> ( (LAMBDA (G) #'(LAMBDA (H) (FUNCALL (FUNCALL F (FUNCALL G G)) H)))
> #'(LAMBDA (G) #'(LAMBDA (H) (FUNCALL (FUNCALL F (FUNCALL G G)) H)))))
>>while in Lisp1, one can write
>> (DEFUN Y (F)
> ((LAMBDA (G) (LAMBDA (H) ((F (G G)) H)))
> (LAMBDA (G) (LAMBDA (H) ((F (G G)) H)))))
Perhaps this is just a matter of taste, but personally, I find the
second (Lisp1) example much easier to write and understand when
sleep-deprived (as I perpetually was in college) than the first
(Lisp2).
Again, to continue:
>The call to this operator in order to compute 6! in Lisp2 would look like
>> (FUNCALL (Y #'(LAMBDA (FN)
> #'(LAMBDA (X)
> (IF (ZEROP X) 1 (* X (FUNCALL FN (- X 1)))))))
> 6)
>>In Lisp1, the same call would look like
>> ((Y (LAMBDA (FN)
> (LAMBDA (X)
> (IF (ZEROP X) 1 (* X (FN (- X 1)))))))
> 6)
Perhaps some would actually prefer the differentiation between
function namespaces and value namespaces, but if I were a
sleep-deprived student in an introductory course in computer science
covering problems similar to those in SICP, I would find the former
(Lisp2) notation much harder to understand at a glance than the latter
(Lisp1) notation. The latter notation allows me to divide the code
into lexical closures just by glancing at the function-names in the
functional positions and the lambda-calls; the former notation forces
me to parse the code manually and to treat instances of 'FUNCALL '#''
as special cases..
-- Benjamin L. Russell