From: Hoan Ton-That
Subject: Hacking CL into a Lisp-1 (an intro to code-walking)
Date: 
Message-ID: <1145519509.825401.204300@u72g2000cwu.googlegroups.com>
;; Hello fellow Lispers,

;; This article will show you how to turn Common Lisp into a Lisp-1.
;; It uses a technique called code walking.  Instead of operating on
;; lists like macros do, we operate on a proper parse tree
;; (represented by CLOS objects, in this case).

;; The arnesi package by Marco Baringer has a code-walker and
;; unwalker, so most of our work is done for us.  So lets step into
;; arnesi:
(in-package :arnesi)

;; We define generic function `lisp1' which converts a Lisp-1 form to
;; a Lisp-2 one.  We'll be defining methods on it with
;; `deflisp1-walker'.
(defgeneric lisp1 (form))

;; This macro runs the form as if were run in a Lisp-1.  Notice how
;; `walk-form' and `unwalk-form' convert the form to and from CLOS
;; objects and lists.
(defmacro with-lisp1 (form)
  (unwalk-form (lisp1 (walk-form form))))

;; We'll use `defun1' to define Lisp-1 style functions.  Everything
;; inside the body is converted from Lisp-1 to Lisp-2.
(defmacro defun1 (name (&rest args) &body body)
  `(defun ,name ,args
     (with-lisp1 (progn ,@body))))

;; This defines a Lisp-1 to Lisp-2 converter.  It takes the class of a
;; CL form object, and its slots as arguments.  It also captures the
;; variable `FORM' for convenience.
(defmacro deflisp1-walker (class (&rest slots) &body body)
  `(defmethod lisp1 ((form ,class))
     (with-slots ,slots form
       ,@body)))

;; This is exactly the same as `make-instance' except for the shorter
;; name.
(defun new (class &rest initargs)
  (apply #'make-instance class initargs))

;; Likewise.
(defun class-name-of (obj)
  (class-name (class-of obj)))

;; Convert a list of forms to Lisp-2.  Very convenient.
(defun lisp1s (forms)
  (mapcar #'lisp1 forms))

;; We keep a list of variables that are bound by lambdas.  Its very
;; inconvenient to pass this around.
(defvar *bound-vars* nil)

;; Okay, by default all forms will stay the same.
(deflisp1-walker form ()
  form)

;; ARNESI> (ppm1 (with-lisp1 2))
;; 2
;; ARNESI> (ppm1 (with-lisp1 'hello))
;; 'HELLO

;; So far, all the same.  Now for if expressions we transform the
;; branches.
(deflisp1-walker if-form (consequent then else)
  (new 'if-form
       :consequent (lisp1 consequent)
       :then (lisp1 then)
       :else (lisp1 else)))

;; ARNESI> (ppm1 (with-lisp1 (if 'hello 'fellow 'lispers)))
;; (IF 'HELLO 'FELLOW 'LISPERS)

;; For any function-form (ie lambda), we just transform the body.  We
;; also must add the parameters to the list of bound variables.
(deflisp1-walker lambda-function-form (arguments body)
  (let ((*bound-vars* (append (mapcar #'name arguments) *bound-vars*)))
    (new 'lambda-function-form
	 :arguments arguments
	 :body      (lisp1s body))))

;; ARNESI> (ppm1 (with-lisp1 (lambda (x y z) x)))
;; #'(LAMBDA (X Y Z) X)

;; If a free variable is bound in the toplevel, *and* not bound by an
;; enclosing lambda, then we'll return that function.  We take
;; advantage of the fact that the `name' slot is shared.
(deflisp1-walker free-variable-reference (name)
  (if (and (fboundp name) (not (member name *bound-vars*)))
      (change-class form 'free-function-object-form)
      form))

;; ARNESI> (ppm1 (with-lisp1 car)) ;(fboundp name) is true
;; #'CAR
;; ARNESI> (ppm1 (with-lisp1 x))   ;(fboundp name) is false
;; X
;; ARNESI> (ppm1 (with-lisp1 (lambda (x) x)))
;; #'(LAMBDA (X) X)
;; ARNESI> (ppm1 (with-lisp1 (lambda (car) car))) ;car is a bound
variable
;; #'(LAMBDA (CAR) CAR)
;; ARNESI> (ppm1 (with-lisp1 (lambda (x) car)))
;; #'(LAMBDA (X) #'CAR) ;car is not bound by a lambda, but bound at the
toplevel

;; We transform all applications so they use explicit funcall.
;; We also must take into account ((a b) c ...) which must also
;; transform the operator accordingly.
(deflisp1-walker application-form (operator arguments)
  (new 'free-application-form
       :operator  'funcall
       :arguments (cons (if (not (typep operator 'form))
			    (lisp1 (walk-form operator))
			    (lisp1 operator))
			(lisp1s arguments))))

;; ARNESI> (ppm1 (with-lisp1 (car '(1 2))))
;; (FUNCALL #'CAR '(1 2))
;; ARNESI> (ppm1 (with-lisp1 (mapcar car '((1 2) (3 4)))))
;; (FUNCALL #'MAPCAR #'CAR '((1 2) (3 4)))
;; ARNESI> (ppm1 (with-lisp1 ((curry + 2) 3)))
;; (FUNCALL (FUNCALL #'CURRY #'+ 2) 3)
;; ARNESI> (ppm1 (with-lisp1 ((lambda (x y) (cons y x)))))
;; (FUNCALL #'(LAMBDA (X Y) (FUNCALL #'CONS Y X)))

;; Here are the rest of the Common Lisp forms:

;; Convert an alist of bindings to Lisp-2.  Used when walking `let',
;; `let*', `flet' and the like.
(defun lisp1b (binds)
  (mapcar #'(lambda (bind)
	      (cons (car bind)
		    (lisp1 (cdr bind))))
	  binds))

(deflisp1-walker function-binding-form (binds body)
  (new (class-name-of form)
       :binds (lisp1b binds)
       :body (lisp1s body)))

(deflisp1-walker variable-binding-form (binds body)
  (new (class-name-of form)
       :binds (lisp1b binds)
       :body  (lisp1s body)))

(deflisp1-walker setq-form (var value)
  (new 'setq-form
       :var   var
       :value (lisp1 value)))

(deflisp1-walker progn-form (body)
  (new 'progn-form
       :body (lisp1s body)))

(deflisp1-walker progv-form (vars-form values-form)
  (new 'progv-form
       :vars-form   (lisp1s vars-form)
       :values-form (lisp1s values-form)))

(deflisp1-walker block-form (name body)
  (new 'block-form
       :name name
       :body (lisp1s body)))

(deflisp1-walker catch-form (tag body)
  (new 'catch-form
       :tag  tag
       :body (lisp1s body)))

(deflisp1-walker multiple-value-call-form (func arguments)
  (new 'multiple-value-call-form
       :func      (lisp1 func)
       :arguments (lisp1s arguments)))

(deflisp1-walker multiple-value-prog1-form (first-form other-forms)
  (new 'multiple-value-prog1-form
       :first-form  (lisp1 first-form)
       :other-forms (lisp1s other-forms)))

(deflisp1-walker symbol-macrolet-form (binds body)
  (new 'symbol-macrolet-form
       :binds (lisp1b binds)
       :body  (lisp1s body)))

(deflisp1-walker tagbody-form (body)
  (new 'tagbody-form
       :body (lisp1s body)))

(deflisp1-walker the-form (type-form value)
  (new 'the-form
       :type-form type-form
       :value     (lisp1 value)))

(deflisp1-walker unwind-protect-form (protected-form cleanup-form)
  (new 'unwind-protect-form
       :protected-form (lisp1 protected-form)
       :cleanup-form   (lisp1 cleanup-form)))

;; We can also define the Y combinator in Lisp-1 style, just for fun:
(defun1 Y (f)
  ((lambda (x)
     (f (lambda (y) ((x x) y))))
   (lambda (x)
     (f (lambda (y) ((x x) y))))))

;; As opposed the the very verbose Lisp-2 style:
(defun Y (f)
  (funcall #'(lambda (x)
	       (funcall f #'(lambda (y) (funcall (funcall x x) y))))
	   #'(lambda (x)
	       (funcall f #'(lambda (y) (funcall (funcall x x) y))))))

;; Now you have the choice between Lisp-1 and Lisp-2 styles.
;; And that folks, is how you do code walking!

;; Hoan

;; For more of a discussion of Lisp-1 vs Lisp-2 see
;; http://www.dreamsongs.com/Separation.html.

From: mac
Subject: Re: Hacking CL into a Lisp-1 (an intro to code-walking)
Date: 
Message-ID: <1145523390.168689.150390@u72g2000cwu.googlegroups.com>
Very cool hack. Ron Garret should be happy that he can use lisp1
functional style in CL.

The code walker and cps transformation in arnesi is very interesting. I
still haven't tackled Lisp in small pieces yet so I cannot fully
understand the code (I think the book explains some of the concepts
behind). But this is in my todo list :-)

Thanks for the interesting article.
-- Mac
From: Ron Garret
Subject: Re: Hacking CL into a Lisp-1 (an intro to code-walking)
Date: 
Message-ID: <rNOSPAMon-5F5B1F.11593421042006@news.gha.chartermi.net>
In article <························@u72g2000cwu.googlegroups.com>,
 "mac" <········@gmail.com> wrote:

> Very cool hack. Ron Garret should be happy that he can use lisp1
> functional style in CL.

Old news.  See http://www.flownet.com/gat/locales.pdf section 5.

This does not address the pedagogy problem.  If you are teaching CL you 
still have to teach it as a Lisp-2 plus a hack for ((lambda ...) ...)

rg
From: Peter Seibel
Subject: Re: Hacking CL into a Lisp-1 (an intro to code-walking)
Date: 
Message-ID: <m2zmiebug2.fsf@gigamonkeys.com>
Ron Garret <·········@flownet.com> writes:

> In article <························@u72g2000cwu.googlegroups.com>,
>  "mac" <········@gmail.com> wrote:
>
>> Very cool hack. Ron Garret should be happy that he can use lisp1
>> functional style in CL.
>
> Old news.  See http://www.flownet.com/gat/locales.pdf section 5.
>
> This does not address the pedagogy problem. If you are teaching CL
> you still have to teach it as a Lisp-2 plus a hack for ((lambda ...)
> ...)

Hmmm, I don't see it that way, and I speak from some experience here.
It seems to me that CL is usefully taught as a Lisp-2 where the 2nd
evaluation rule (i.e. the one used to evaluate the CAR's of list forms
and by the special operator FUNCTION) knows about two kinds of
function names, symbols and "eponymous" functions, i.e. lambda's. The
only glitch the pedagog must handwave around is the fact that after
you say:

  (defun (setf foo) (x ...) ....)

then:

  (function (setf foo)) => #<Interpreted Function (SETF FOO)>

but:

  ((setf foo) 20 ...)

is an error. But basically you can say (in only slight contradiction
of the Hyperspec) that a function "name" is a symbol, a LAMBDA
expression or a two-item list of the form (SETF <symbol>) and that the
FUNCTION special operator understands all three kinds of names and
either of the first two, but not the third, can be used in the CAR
position of a list form.

-Peter

-- 
Peter Seibel           * ·····@gigamonkeys.com
Gigamonkeys Consulting * http://www.gigamonkeys.com/
Practical Common Lisp  * http://www.gigamonkeys.com/book/
From: Ron Garret
Subject: Re: Hacking CL into a Lisp-1 (an intro to code-walking)
Date: 
Message-ID: <rNOSPAMon-F2C1BB.15515122042006@news.gha.chartermi.net>
In article <··············@gigamonkeys.com>,
 Peter Seibel <·····@gigamonkeys.com> wrote:

> Ron Garret <·········@flownet.com> writes:
> 
> > In article <························@u72g2000cwu.googlegroups.com>,
> >  "mac" <········@gmail.com> wrote:
> >
> >> Very cool hack. Ron Garret should be happy that he can use lisp1
> >> functional style in CL.
> >
> > Old news.  See http://www.flownet.com/gat/locales.pdf section 5.
> >
> > This does not address the pedagogy problem. If you are teaching CL
> > you still have to teach it as a Lisp-2 plus a hack for ((lambda ...)
> > ...)
> 
> Hmmm, I don't see it that way, and I speak from some experience here.
> It seems to me that CL is usefully taught as a Lisp-2 where the 2nd
> evaluation rule (i.e. the one used to evaluate the CAR's of list forms
> and by the special operator FUNCTION) knows about two kinds of
> function names, symbols and "eponymous" functions, i.e. lambda's. The
> only glitch the pedagog must handwave around is the fact that after
> you say:
> 
>   (defun (setf foo) (x ...) ....)
> 
> then:
> 
>   (function (setf foo)) => #<Interpreted Function (SETF FOO)>
> 
> but:
> 
>   ((setf foo) 20 ...)
> 
> is an error. But basically you can say (in only slight contradiction
> of the Hyperspec) that a function "name" is a symbol, a LAMBDA
> expression or a two-item list of the form (SETF <symbol>)

Of course you can say that, but it's not a "slight contradiction to the 
spec", it's an outright lie:

? (defun (setf foo) () t)
(SETF FOO)
? ((setf foo))
Error: Car of ((SETF FOO)) is not a function name or lambda-expression.


> and that the
> FUNCTION special operator understands all three kinds of names and
> either of the first two, but not the third, can be used in the CAR
> position of a list form.

I don't see how this is substantially different from what I said.  
Whether you choose to present it as a hack for lambda or an anti-hack 
for setf, it's still a hack.  (Frankly, I think your approach is much 
worse because it's a hack AND a lie.  My way it's just a hack.)

rg
From: Peter Seibel
Subject: Re: Hacking CL into a Lisp-1 (an intro to code-walking)
Date: 
Message-ID: <m2zmid9n5x.fsf@gigamonkeys.com>
Ron Garret <·········@flownet.com> writes:

> In article <··············@gigamonkeys.com>,
>  Peter Seibel <·····@gigamonkeys.com> wrote:

>> is an error. But basically you can say (in only slight contradiction
>> of the Hyperspec) that a function "name" is a symbol, a LAMBDA
>> expression or a two-item list of the form (SETF <symbol>)
>
> Of course you can say that, but it's not a "slight contradiction to the 
> spec", it's an outright lie:
>
> ? (defun (setf foo) () t)
> (SETF FOO)
> ? ((setf foo))
> Error: Car of ((SETF FOO)) is not a function name or lambda-expression.

Actually your implementation is lying to you. According to the
hyperspec a list of the form (SETF <symbol>) *is* a function name.
(Check the glossary entry for "function name".) The slight
contradiction to the spec that I was ignoring is that *lambda
expressions* are not, technically speaking, "function names".

Without contradicting the spec we can say the FUNCTION special
operator takes as it's argument a function name or a lambda expression
while the CAR of a list form representing a function call must be
either a symbol function name or a lambda expression.

>> and that the FUNCTION special operator understands all three kinds
>> of names and either of the first two, but not the third, can be
>> used in the CAR position of a list form.
>
> I don't see how this is substantially different from what I said.  
> Whether you choose to present it as a hack for lambda or an anti-hack 
> for setf, it's still a hack.  (Frankly, I think your approach is much 
> worse because it's a hack AND a lie.  My way it's just a hack.)

Well the difference is that I'd say the treatment of lambda
expressions as function eponyms, if not technically nyms, is perfectly
consistent, i.e. anywhere you can use a function name to refer to a
function you can also use a lambda expression. (Actually that sort of
makes the distinction between an eponym and a proper name clear--the
one place you *can't* use a lambda expression is, of course, when
giving a function it's name, i.e. in a DEFUN, FLET, or LABELS, since
an eponym by it's nature is *already* the name of the thing it names.)
The only inconsistency (hack, if you will) is that (SETF <symbol>)
names can be used with DEFUN (and, according to the HyperSpec with
FLET and LABELS though that doesn't seem to work in Allegro) and as
arguments to FUNCTION but not in the CAR position of a function call
form.

-Peter

-- 
Peter Seibel           * ·····@gigamonkeys.com
Gigamonkeys Consulting * http://www.gigamonkeys.com/
Practical Common Lisp  * http://www.gigamonkeys.com/book/
From: Ron Garret
Subject: Re: Hacking CL into a Lisp-1 (an intro to code-walking)
Date: 
Message-ID: <rNOSPAMon-BE1F5E.17324422042006@news.gha.chartermi.net>
In article <··············@gigamonkeys.com>,
 Peter Seibel <·····@gigamonkeys.com> wrote:

> Ron Garret <·········@flownet.com> writes:
> 
> > In article <··············@gigamonkeys.com>,
> >  Peter Seibel <·····@gigamonkeys.com> wrote:
> 
> >> is an error. But basically you can say (in only slight contradiction
> >> of the Hyperspec) that a function "name" is a symbol, a LAMBDA
> >> expression or a two-item list of the form (SETF <symbol>)
> >
> > Of course you can say that, but it's not a "slight contradiction to the 
> > spec", it's an outright lie:
> >
> > ? (defun (setf foo) () t)
> > (SETF FOO)
> > ? ((setf foo))
> > Error: Car of ((SETF FOO)) is not a function name or lambda-expression.
> 
> Actually your implementation is lying to you.

Whaddya know.  My bad.  Sorry.  I was confusing the definitions of 
function names and function designators (I think -- it's all so horribly 
confusing sometimes).

> Without contradicting the spec we can say the FUNCTION special
> operator takes as it's argument a function name or a lambda expression
> while the CAR of a list form representing a function call must be
> either a symbol function name or a lambda expression.

True.  Still, one could forgive a newcomer for wondering what the payoff 
is in all this complexity.

> >> and that the FUNCTION special operator understands all three kinds
> >> of names and either of the first two, but not the third, can be
> >> used in the CAR position of a list form.
> >
> > I don't see how this is substantially different from what I said.  
> > Whether you choose to present it as a hack for lambda or an anti-hack 
> > for setf, it's still a hack.  (Frankly, I think your approach is much 
> > worse because it's a hack AND a lie.  My way it's just a hack.)
> 
> Well the difference is that I'd say the treatment of lambda
> expressions as function eponyms,

Dictionary.com says that "eponym" means:


   1   A person whose name is or is thought to be the source of the name 
of something, such as a city, country, or era. For example, Romulus is 
the eponym of Rome.
   2  Medicine. A name of a drug, structure, or disease based on or 
derived from the name of a person.

Accordingly, the above makes no sense to me.

> if not technically nyms,

Nyms is not an english word as far as I can determine.  (Remember, we're 
talking about pedagogy here, so this is not a trivial detail.)

> is perfectly
> consistent, i.e. anywhere you can use a function name to refer to a
> function you can also use a lambda expression.

Not so:

? (defun foo () t)
FOO
? (setf function-name-1 'foo)
FOO
? (setf function-name-2 '(lambda () t))
(LAMBDA NIL T)
? (funcall function-name-1)
T
? (funcall function-name-2)
> Error: (LAMBDA NIL T) can't be FUNCALLed or APPLYed.


rg
From: Thomas F. Burdick
Subject: Re: Hacking CL into a Lisp-1 (an intro to code-walking)
Date: 
Message-ID: <xcvmzecivsd.fsf@conquest.OCF.Berkeley.EDU>
Ron Garret <·········@flownet.com> writes:

> In article <··············@gigamonkeys.com>,
>  Peter Seibel <·····@gigamonkeys.com> wrote:
>
> > Well the difference is that I'd say the treatment of lambda
> > expressions as function eponyms,
> 
> Dictionary.com says that "eponym" means:

I think he really wanted to say something closer to autonym.  Or at
least the French word "autonyme", since I can't find a reference in
English to autonym meaning a word designating itself (as it just did
there).

-- 
           /|_     .-----------------------.                        
         ,'  .\  / | Free Mumia Abu-Jamal! |
     ,--'    _,'   | Abolish the racist    |
    /       /      | death penalty!        |
   (   -.  |       `-----------------------'
   |     ) |                               
  (`-.  '--.)                              
   `. )----'                               
From: Curt
Subject: Re: Hacking CL into a Lisp-1 (an intro to code-walking)
Date: 
Message-ID: <slrne4mpbe.3rr.curty@einstein.electron.net>
On 2006-04-23, Thomas F. Burdick <···@conquest.OCF.Berkeley.EDU> wrote:

>> Dictionary.com says that "eponym" means:
>
> I think he really wanted to say something closer to autonym.  Or at
> least the French word "autonyme", since I can't find a reference in
> English to autonym meaning a word designating itself (as it just did
> there).
>

I googled this one:

http://www.fun-with-words.com/nym_words.html
From: Peter Seibel
Subject: Re: Hacking CL into a Lisp-1 (an intro to code-walking)
Date: 
Message-ID: <m2r73p9jmy.fsf@gigamonkeys.com>
Ron Garret <·········@flownet.com> writes:

> Dictionary.com says that "eponym" means:
>
>    1   A person whose name is or is thought to be the source of the name 
> of something, such as a city, country, or era. For example, Romulus is 
> the eponym of Rome.
>    2  Medicine. A name of a drug, structure, or disease based on or 
> derived from the name of a person.
>
> Accordingly, the above makes no sense to me.

Well, it may be stretching the metaphor a bit but a lambda expression
both is the function (i.e. it is Romulus) and it gives the function
(what passes for) it's name.

>> if not technically nyms,
>
> Nyms is not an english word as far as I can determine. (Remember,
> we're talking about pedagogy here, so this is not a trivial detail.)

I'm sorry if you didn't get the joke and doubly sorry if it actually
confused you. Humour is always a tricky thing, but it can be a useful
pedagogical tool. (Helps keep the student from falling asleep,
drooling on your book, and getting the pages stuck to their face.)

>> is perfectly consistent, i.e. anywhere you can use a function name
>> to refer to a function you can also use a lambda expression.
>
> Not so:
>
> ? (defun foo () t)
> FOO
> ? (setf function-name-1 'foo)
> FOO
> ? (setf function-name-2 '(lambda () t))
> (LAMBDA NIL T)
> ? (funcall function-name-1)
> T
> ? (funcall function-name-2)
>> Error: (LAMBDA NIL T) can't be FUNCALLed or APPLYed.

So this is where you trip over the function name vs function
designator distinction. The argument to FUNCALL is a function
designator, not a function name. So this is, technically speaking, not
a place you can use a function name thus does not contradict my claim.
Which is not to say that there isn't some operator in Common Lisp that
is documented to accept a function name but not a lambda expression,
but I can't think of any. (Moreover, it makes a certain logical sense
that there wouldn't be--the only two places that *have* to deal with
function names are the FUNCTION special operator and the basic
evaluation rule for function call forms. Everywhere else function
designators are a better choice since you can always use the FUNCTION
special operator to translate from names to function objects.

-Peter

-- 
Peter Seibel           * ·····@gigamonkeys.com
Gigamonkeys Consulting * http://www.gigamonkeys.com/
Practical Common Lisp  * http://www.gigamonkeys.com/book/
From: Ron Garret
Subject: Re: Hacking CL into a Lisp-1 (an intro to code-walking)
Date: 
Message-ID: <rNOSPAMon-34DC63.22465322042006@news.gha.chartermi.net>
In article <··············@gigamonkeys.com>,
 Peter Seibel <·····@gigamonkeys.com> wrote:

> Ron Garret <·········@flownet.com> writes:
> 
> > Dictionary.com says that "eponym" means:
> >
> >    1   A person whose name is or is thought to be the source of the name 
> > of something, such as a city, country, or era. For example, Romulus is 
> > the eponym of Rome.
> >    2  Medicine. A name of a drug, structure, or disease based on or 
> > derived from the name of a person.
> >
> > Accordingly, the above makes no sense to me.
> 
> Well, it may be stretching the metaphor a bit but a lambda expression
> both is the function (i.e. it is Romulus) and it gives the function
> (what passes for) it's name.

But a lambda expression isn't a function.  It is a list whose CAR is the 
symbol LAMBDA.  Lists aren't functions, at least not in CL.  (Lists ARE 
functions in e.g. NewLisp, which IMO is a Really Bad Idea (tm).)

> >> is perfectly consistent, i.e. anywhere you can use a function name
> >> to refer to a function you can also use a lambda expression.
> >
> > Not so:
> >
> > ? (defun foo () t)
> > FOO
> > ? (setf function-name-1 'foo)
> > FOO
> > ? (setf function-name-2 '(lambda () t))
> > (LAMBDA NIL T)
> > ? (funcall function-name-1)
> > T
> > ? (funcall function-name-2)
> >> Error: (LAMBDA NIL T) can't be FUNCALLed or APPLYed.
> 
> So this is where you trip over the function name vs function
> designator distinction. The argument to FUNCALL is a function
> designator, not a function name. So this is, technically speaking, not
> a place you can use a function name thus does not contradict my claim.

There are two ways to interpret the claim "anywhere you can use a 
function name to refer to a function you can also use a lambda 
expression."

The first interpretation is: "Anywhere you can use *ANY* (object that 
can serve as a) function name to refer to a function you can also use a 
lambda expression."

The second interpretation is: "Anywhere the spec says you can use a 
function name, you can also use a lambda expression."

Because the spec says that a lambda expression IS a function name, the 
second interpretation is true by definition, which makes the claim 
vacuous.  Accordingly I assumed the first interpretation.

BTW (I'm sure you know this but just for the benefit of any lurkers out 
there) there are actually FOUR distinct concepts in CL:

Functions
Function names
Function designators
Extended function designators

Discerning the differences between them is left as an exercise.

In any case, popping the stack a few frames, nothing you have said 
dissuades me in any way from my belief that CL presents significant 
pedagogical challenges.

rg
From: Peter Seibel
Subject: Re: Hacking CL into a Lisp-1 (an intro to code-walking)
Date: 
Message-ID: <m2hd4ka12m.fsf@gigamonkeys.com>
Ron Garret <·········@flownet.com> writes:

> There are two ways to interpret the claim "anywhere you can use a
> function name to refer to a function you can also use a lambda
> expression."
>
> The first interpretation is: "Anywhere you can use *ANY* (object that 
> can serve as a) function name to refer to a function you can also use a 
> lambda expression."
>
> The second interpretation is: "Anywhere the spec says you can use a 
> function name, you can also use a lambda expression."
>
> Because the spec says that a lambda expression IS a function name, the 
> second interpretation is true by definition, which makes the claim 
> vacuous.  Accordingly I assumed the first interpretation.

Except the spec *doesn't* say a lambda expression is a function name.
That's my whole point.

> BTW (I'm sure you know this but just for the benefit of any lurkers out 
> there) there are actually FOUR distinct concepts in CL:
>
> Functions
> Function names
> Function designators
> Extended function designators
>
> Discerning the differences between them is left as an exercise.

One easily solved by looking in the Hyperspec's glossary. For the lazy here it is:

  Functions -- the actual function objects.

  Function names -- symbols and lists of the form (SETF <symbol>)

  Function designators -- symbols and lambda expressions

  Extended function designators -- function names and lambda expressions

> In any case, popping the stack a few frames, nothing you have said 
> dissuades me in any way from my belief that CL presents significant 
> pedagogical challenges.

Oh, you don't have to tell *me* about CL's pedagogical challenges. Why
do you think it took me two years to write my book? But I think the
challenges, such as they are, come from two causes:

 1) Many parts of Common Lisp are easy to understand but only if you
    can grasp a few subtle ideas. Since subtle ideas are, well, subtle
    they're hard to convey.

 2) As a Lisp pedagog you can't count on your students cutting Lisp
    any slack. Minor glitches and oddities, such as exist in any
    language, are too often used as an excuse to give up on Lisp. When
    writing Practical Common Lisp I took the approach of trying to
    make the rewards of learning Lisp more obvious and working really
    hard to find good ways to explain things.

What I found interesting was how often things that at first appeared
to fall in the glitches and oddities category would turn out to
actually be explicable in terms of some subtle idea. Unfortunately
that doesn't make them any easier to explain. Others, of course,
remain glitches and oddities no matter how you slice it. And even the
worst glitches in Common Lisp usually have some interesting history
behind them--often a history that teaches us lessons about how
computer languages are actually designed.

I do think folks who moan and groan all the time about how hard Lisp
is to teach or learn actually make the Lisp pedagog's job harder by
preconditiong would-be Lispers to beleive it's likely too hard for
them to learn. So ease up there. Or, to paraphrase Jon Stewart: "Stop
it, you're hurting Lisp."

-Peter

-- 
Peter Seibel           * ·····@gigamonkeys.com
Gigamonkeys Consulting * http://www.gigamonkeys.com/
Practical Common Lisp  * http://www.gigamonkeys.com/book/
From: Ron Garret
Subject: Re: Hacking CL into a Lisp-1 (an intro to code-walking)
Date: 
Message-ID: <rNOSPAMon-93C2C6.10062823042006@news.gha.chartermi.net>
In article <··············@gigamonkeys.com>,
 Peter Seibel <·····@gigamonkeys.com> wrote:

> Ron Garret <·········@flownet.com> writes:
> 
> > There are two ways to interpret the claim "anywhere you can use a
> > function name to refer to a function you can also use a lambda
> > expression."
> >
> > The first interpretation is: "Anywhere you can use *ANY* (object that 
> > can serve as a) function name to refer to a function you can also use a 
> > lambda expression."
> >
> > The second interpretation is: "Anywhere the spec says you can use a 
> > function name, you can also use a lambda expression."
> >
> > Because the spec says that a lambda expression IS a function name, the 
> > second interpretation is true by definition, which makes the claim 
> > vacuous.  Accordingly I assumed the first interpretation.
> 
> Except the spec *doesn't* say a lambda expression is a function name.
> That's my whole point.

You're right.  The spec says "lambda expression n. a list which can be 
used in place of a function name in certain contexts."  (I had forgotten 
about the "in certain contexts" disclaimer, though I suppose technically 
lambda expression still wouldn't BE function names even without it.)

So your claim is just flat-out false according to the spec.  It is not 
the case, according to the spec, that "anywhere you can use a function 
name to refer to a function you can also use a lambda expression."  It 
is only true (according to the spec) "in certain contexts."

> > In any case, popping the stack a few frames, nothing you have said 
> > dissuades me in any way from my belief that CL presents significant 
> > pedagogical challenges.
> 
> Oh, you don't have to tell *me* about CL's pedagogical challenges. Why
> do you think it took me two years to write my book? But I think the
> challenges, such as they are, come from two causes:
> 
>  1) Many parts of Common Lisp are easy to understand but only if you
>     can grasp a few subtle ideas. Since subtle ideas are, well, subtle
>     they're hard to convey.

What subtle idea lies behind the distinction between functions, function 
names, function designators and extended function designators?  BTW, 
there is actually a FIFTH concept as well: "a symbol naming a function", 
which is introduced in section 3.1.2.1.2.3 in order to, as far as I can 
tell, prevent ((setf ...) ...) from working as it intuitively should.  
I've been studying this for 20 years and in all honesty it has always 
just looked like a hack to me.

>  2) As a Lisp pedagog you can't count on your students cutting Lisp
>     any slack. Minor glitches and oddities, such as exist in any
>     language, are too often used as an excuse to give up on Lisp. When
>     writing Practical Common Lisp I took the approach of trying to
>     make the rewards of learning Lisp more obvious and working really
>     hard to find good ways to explain things.
> 
> What I found interesting was how often things that at first appeared
> to fall in the glitches and oddities category would turn out to
> actually be explicable in terms of some subtle idea. Unfortunately
> that doesn't make them any easier to explain.

In my experience, understanding the subtle idea behind apparent 
complexity ALWAYS makes it easier to explain.  (My favorite example is 
http://www.flownet.com/ron/QM.pdf)  Could you give an example where it 
doesn't?

> Others, of course,
> remain glitches and oddities no matter how you slice it. And even the
> worst glitches in Common Lisp usually have some interesting history
> behind them--often a history that teaches us lessons about how
> computer languages are actually designed.

Living with those glitches forever is a high price to pay for a history 
lesson IMO.

> I do think folks who moan and groan all the time about how hard Lisp
> is to teach or learn actually make the Lisp pedagog's job harder by
> preconditiong would-be Lispers to beleive it's likely too hard for
> them to learn. So ease up there. Or, to paraphrase Jon Stewart: "Stop
> it, you're hurting Lisp."

Long term improvement often requires some short term pain and sacrifice.  
Sorry, but that's just the way the world is.

rg
From: Peter Seibel
Subject: Re: Hacking CL into a Lisp-1 (an intro to code-walking)
Date: 
Message-ID: <m28xpw9nwe.fsf@gigamonkeys.com>
Ron Garret <·········@flownet.com> writes:

> In article <··············@gigamonkeys.com>,
>  Peter Seibel <·····@gigamonkeys.com> wrote:
>
>> Ron Garret <·········@flownet.com> writes:
>> 
>> > There are two ways to interpret the claim "anywhere you can use a
>> > function name to refer to a function you can also use a lambda
>> > expression."
>> >
>> > The first interpretation is: "Anywhere you can use *ANY* (object that 
>> > can serve as a) function name to refer to a function you can also use a 
>> > lambda expression."
>> >
>> > The second interpretation is: "Anywhere the spec says you can use a 
>> > function name, you can also use a lambda expression."
>> >
>> > Because the spec says that a lambda expression IS a function name, the 
>> > second interpretation is true by definition, which makes the claim 
>> > vacuous.  Accordingly I assumed the first interpretation.
>> 
>> Except the spec *doesn't* say a lambda expression is a function name.
>> That's my whole point.
>
> You're right.  The spec says "lambda expression n. a list which can be 
> used in place of a function name in certain contexts."  (I had forgotten 
> about the "in certain contexts" disclaimer, though I suppose technically 
> lambda expression still wouldn't BE function names even without it.)
>
> So your claim is just flat-out false according to the spec. It is
> not the case, according to the spec, that "anywhere you can use a
> function name to refer to a function you can also use a lambda
> expression." It is only true (according to the spec) "in certain
> contexts."

Well, I tried--and probably failed--to draw a distinction there with
my use of "to refer to" to exclude the uses of function names in
definitional forms. As far as I know the only places in the language
that call for a function name (as opposed to a function designator of
some sort) are:

  1. The second element of a FUNCTION form.

  2. The first element of a list representing a function call form.

  3. The second element of a DEFUN form.

  4. The second first element of a function definition in a FLET and LABELS.

By "anywhere you can use a function name to refer to a function" I
meant to include 1 and 2 and exclude 3 and 4. That I didn't make that
distinction sufficiently clear is my fault. And it's possible that
there may be other places in the language that call for a function
name; if there are I'd love to be reminded what they are so I can see
if they fit into this analysis.

>> > In any case, popping the stack a few frames, nothing you have
>> > said dissuades me in any way from my belief that CL presents
>> > significant pedagogical challenges.
>> 
>> Oh, you don't have to tell *me* about CL's pedagogical challenges. Why
>> do you think it took me two years to write my book? But I think the
>> challenges, such as they are, come from two causes:
>> 
>>  1) Many parts of Common Lisp are easy to understand but only if you
>>     can grasp a few subtle ideas. Since subtle ideas are, well, subtle
>>     they're hard to convey.
>
> What subtle idea lies behind the distinction between functions, function 
> names, function designators and extended function designators?  BTW, 
> there is actually a FIFTH concept as well: "a symbol naming a function", 
> which is introduced in section 3.1.2.1.2.3 in order to, as far as I can 
> tell, prevent ((setf ...) ...) from working as it intuitively should.  
> I've been studying this for 20 years and in all honesty it has always 
> just looked like a hack to me.

Well, sometimes the hacks are subtle. ;-) Seriously, in this
situation, there are two reasons, that things aren't nice and tidily
orthogonal.

  1) It is desirable to be able to FUNCALL and APPLY globally defined
     functions through a symbol. That is, those two functions (and
     other functions that eventually FUNCALL or APPLY one of their
     arguments) could have been defined to only take a proper function
     rather than a function designator and to get the current behavior
     we could always write:

       (apply (if (symbolp fn) (symbol-function fn) fn) some-list)

    instead of:

       (apply fn some-list)

  2) It is handy to be able to customize SETF via (defun (setf foo) ...)

The 1st point seems like a good design choice, though it adds a bit of
non-orthogonality to the langauge. And the 2nd is also a plesant
convenience that introduces the notion that a list of theform (SETF
<symbol>) is a "function name" in the sense of "a thing that can be
used as the second element of a DEFUN form". They *could* have gone
whole hog and made:

  ((setf foo) x)

another way of spelling:

  (setf (foo) x)

But they didn't. I'm not even convinced that it would have been better
if they had--just another darn thing to explain, why there are these
two spellings for the same thing.

>>  2) As a Lisp pedagog you can't count on your students cutting Lisp
>>     any slack. Minor glitches and oddities, such as exist in any
>>     language, are too often used as an excuse to give up on Lisp. When
>>     writing Practical Common Lisp I took the approach of trying to
>>     make the rewards of learning Lisp more obvious and working really
>>     hard to find good ways to explain things.
>> 
>> What I found interesting was how often things that at first appeared
>> to fall in the glitches and oddities category would turn out to
>> actually be explicable in terms of some subtle idea. Unfortunately
>> that doesn't make them any easier to explain.
>
> In my experience, understanding the subtle idea behind apparent 
> complexity ALWAYS makes it easier to explain.  (My favorite example is 
> http://www.flownet.com/ron/QM.pdf)  Could you give an example where it 
> doesn't?

I'd agree that understanding the subtle idea yourself *does* always
make it easier to explain. It may even be required before you can give
a proper explanation. But forcing your students/readers/conversational
partners/victims to understand the subtle idea as a prerequisite to
understanding the thing they actually want to know about is not always
a winning strategy, in my experience.

-Peter

-- 
Peter Seibel           * ·····@gigamonkeys.com
Gigamonkeys Consulting * http://www.gigamonkeys.com/
Practical Common Lisp  * http://www.gigamonkeys.com/book/
From: Ron Garret
Subject: Re: Hacking CL into a Lisp-1 (an intro to code-walking)
Date: 
Message-ID: <rNOSPAMon-52AEC7.13114723042006@news.gha.chartermi.net>
In article <··············@gigamonkeys.com>,
 Peter Seibel <·····@gigamonkeys.com> wrote:

> Ron Garret <·········@flownet.com> writes:
> 
> > In article <··············@gigamonkeys.com>,
> >  Peter Seibel <·····@gigamonkeys.com> wrote:
> >
> >> Ron Garret <·········@flownet.com> writes:
> >> 
> >> > There are two ways to interpret the claim "anywhere you can use a
> >> > function name to refer to a function you can also use a lambda
> >> > expression."
> >> >
> >> > The first interpretation is: "Anywhere you can use *ANY* (object that 
> >> > can serve as a) function name to refer to a function you can also use a 
> >> > lambda expression."
> >> >
> >> > The second interpretation is: "Anywhere the spec says you can use a 
> >> > function name, you can also use a lambda expression."
> >> >
> >> > Because the spec says that a lambda expression IS a function name, the 
> >> > second interpretation is true by definition, which makes the claim 
> >> > vacuous.  Accordingly I assumed the first interpretation.
> >> 
> >> Except the spec *doesn't* say a lambda expression is a function name.
> >> That's my whole point.
> >
> > You're right.  The spec says "lambda expression n. a list which can be 
> > used in place of a function name in certain contexts."  (I had forgotten 
> > about the "in certain contexts" disclaimer, though I suppose technically 
> > lambda expression still wouldn't BE function names even without it.)
> >
> > So your claim is just flat-out false according to the spec. It is
> > not the case, according to the spec, that "anywhere you can use a
> > function name to refer to a function you can also use a lambda
> > expression." It is only true (according to the spec) "in certain
> > contexts."
> 
> Well, I tried--and probably failed--to draw a distinction there with
> my use of "to refer to" to exclude the uses of function names in
> definitional forms. As far as I know the only places in the language
> that call for a function name (as opposed to a function designator of
> some sort) are:
> 
>   1. The second element of a FUNCTION form.
> 
>   2. The first element of a list representing a function call form.
> 
>   3. The second element of a DEFUN form.
> 
>   4. The second first element of a function definition in a FLET and LABELS.
> 
> By "anywhere you can use a function name to refer to a function" I
> meant to include 1 and 2 and exclude 3 and 4. That I didn't make that
> distinction sufficiently clear is my fault. And it's possible that
> there may be other places in the language that call for a function
> name; if there are I'd love to be reminded what they are so I can see
> if they fit into this analysis.

Well, I don't want to lose sight of the pedagogical forest by focusing 
too much on the function name tree.

> >> > In any case, popping the stack a few frames, nothing you have
> >> > said dissuades me in any way from my belief that CL presents
> >> > significant pedagogical challenges.
> >> 
> >> Oh, you don't have to tell *me* about CL's pedagogical challenges. Why
> >> do you think it took me two years to write my book? But I think the
> >> challenges, such as they are, come from two causes:
> >> 
> >>  1) Many parts of Common Lisp are easy to understand but only if you
> >>     can grasp a few subtle ideas. Since subtle ideas are, well, subtle
> >>     they're hard to convey.
> >
> > What subtle idea lies behind the distinction between functions, function 
> > names, function designators and extended function designators?  BTW, 
> > there is actually a FIFTH concept as well: "a symbol naming a function", 
> > which is introduced in section 3.1.2.1.2.3 in order to, as far as I can 
> > tell, prevent ((setf ...) ...) from working as it intuitively should.  
> > I've been studying this for 20 years and in all honesty it has always 
> > just looked like a hack to me.
> 
> Well, sometimes the hacks are subtle. ;-) Seriously, in this
> situation, there are two reasons, that things aren't nice and tidily
> orthogonal.
> 
>   1) It is desirable to be able to FUNCALL and APPLY globally defined
>      functions through a symbol.

Why?

>      That is, those two functions (and
>      other functions that eventually FUNCALL or APPLY one of their
>      arguments) could have been defined to only take a proper function
>      rather than a function designator and to get the current behavior
>      we could always write:
> 
>        (apply (if (symbolp fn) (symbol-function fn) fn) some-list)
> 
>     instead of:
> 
>        (apply fn some-list)

Right.  So at best this hack saves you that bit of typing.  I do not 
mean to denigrate the benefit of saving a bit of typing, especially if 
it's a very common idiom.  But why is THAT bit of typing so much more 
important than, e.g. this bit of typing:

(cond ((symbolp fn) (symbol-function fn))
      ((stringp fn) (symbol-function (intern fn)))
      ((and (consp fn) (eq (car fn) 'lambda)) (compile fn))
      ((and (consp fn) (eq (car fn) 'setf)) ...)
      (t fn))

Note, by the way, that the preceding discussion is applicable ONLY if 
you don't know what kind of object you have when you're writing the 
code.  If you know which you have then you don't need the conditional.  
Now, I can't think of a single situation where you would not know at 
code-writing time whether you have a symbol or a function object that 
would not be the result of Really Bad Design (tm).

So I am still in the dark about the Subtle Idea hiding behind this mess.  
Please enlighten me.

>   2) It is handy to be able to customize SETF via (defun (setf foo) ...)
> 
> The 1st point seems like a good design choice,

Why?

> though it adds a bit of
> non-orthogonality to the langauge. And the 2nd is also a plesant
> convenience that introduces the notion that a list of theform (SETF
> <symbol>) is a "function name" in the sense of "a thing that can be
> used as the second element of a DEFUN form". They *could* have gone
> whole hog and made:
> 
>   ((setf foo) x)
> 
> another way of spelling:
> 
>   (setf (foo) x)
> 
> But they didn't. I'm not even convinced that it would have been better
> if they had--just another darn thing to explain, why there are these
> two spellings for the same thing.

Another thing they could have done is borrowed a page from the T 
playbook and made (SETTER FOO) be the name of the setter function so as 
not to overload the symbol SETF to be both a macro and the prelude for 
certain kinds of function names.  That would have made the two cases be:

((setter foo) ...)
(setf (foo) ...)

which could be understood without having to explain "another darn thing."

But they didn't.

> >>  2) As a Lisp pedagog you can't count on your students cutting Lisp
> >>     any slack. Minor glitches and oddities, such as exist in any
> >>     language, are too often used as an excuse to give up on Lisp. When
> >>     writing Practical Common Lisp I took the approach of trying to
> >>     make the rewards of learning Lisp more obvious and working really
> >>     hard to find good ways to explain things.
> >> 
> >> What I found interesting was how often things that at first appeared
> >> to fall in the glitches and oddities category would turn out to
> >> actually be explicable in terms of some subtle idea. Unfortunately
> >> that doesn't make them any easier to explain.
> >
> > In my experience, understanding the subtle idea behind apparent 
> > complexity ALWAYS makes it easier to explain.  (My favorite example is 
> > http://www.flownet.com/ron/QM.pdf)  Could you give an example where it 
> > doesn't?
> 
> I'd agree that understanding the subtle idea yourself *does* always
> make it easier to explain. It may even be required before you can give
> a proper explanation. But forcing your students/readers/conversational
> partners/victims to understand the subtle idea as a prerequisite to
> understanding the thing they actually want to know about is not always
> a winning strategy, in my experience.

In my experience, when that appears to be the case, you haven't really 
understood it yourself (or perhaps you are just unwilling to face the 
fact that what you thought was a Subtle Idea is really a Horrible Hack).

http://chronicle.com/jobs/v45/i47/4547ctlyst.htm

rg
From: Peter Seibel
Subject: Re: Hacking CL into a Lisp-1 (an intro to code-walking)
Date: 
Message-ID: <m2u08k81nh.fsf@gigamonkeys.com>
Ron Garret <·········@flownet.com> writes:

>>   1) It is desirable to be able to FUNCALL and APPLY globally defined
>>      functions through a symbol.
>
> Why?

Because it provides a level of indirection that allows code to pick up
changes in function definitions. Consider the difference between:

  (funcall 'foo x y z)

and:

  (funcall #'foo x y z)

in the face of a redefinition of FOO. Given that that kind of dynamic
redefinition is an import part of The Lisp Way, this seems like a
coherent design choice. (Yes, it is non-orthogonal. If you want a
language that more consistently strives for orthogonality Scheme is
over there. But I know you don't want Scheme so I assume you're not
really hung up on orthogonality for it's own sake.)

>>      That is, those two functions (and
>>      other functions that eventually FUNCALL or APPLY one of their
>>      arguments) could have been defined to only take a proper function
>>      rather than a function designator and to get the current behavior
>>      we could always write:
>> 
>>        (apply (if (symbolp fn) (symbol-function fn) fn) some-list)
>> 
>>     instead of:
>> 
>>        (apply fn some-list)
>
> Right.  So at best this hack saves you that bit of typing.  I do not 
> mean to denigrate the benefit of saving a bit of typing, especially if 
> it's a very common idiom.  But why is THAT bit of typing so much more 
> important than, e.g. this bit of typing:
>
> (cond ((symbolp fn) (symbol-function fn))
>       ((stringp fn) (symbol-function (intern fn)))
>       ((and (consp fn) (eq (car fn) 'lambda)) (compile fn))
>       ((and (consp fn) (eq (car fn) 'setf)) ...)
>       (t fn))
>
> Note, by the way, that the preceding discussion is applicable ONLY if 
> you don't know what kind of object you have when you're writing the 
> code.  If you know which you have then you don't need the conditional.  
> Now, I can't think of a single situation where you would not know at 
> code-writing time whether you have a symbol or a function object that 
> would not be the result of Really Bad Design (tm).

See my example above. In both cases I know exactly what kind of object
I have at hand but the two expressions are not equivalent. 

> So I am still in the dark about the Subtle Idea hiding behind this mess.  
> Please enlighten me.

I think it's the old chestnut, "Any software problem can be solved
with another layer of indirection."

> Another thing they could have done is borrowed a page from the T 
> playbook and made (SETTER FOO) be the name of the setter function so as 
> not to overload the symbol SETF to be both a macro and the prelude for 
> certain kinds of function names.  That would have made the two cases be:
>
> ((setter foo) ...)
> (setf (foo) ...)
>
> which could be understood without having to explain "another darn thing."
>
> But they didn't.

No they didn't. Oh well.

>> I'd agree that understanding the subtle idea yourself *does* always
>> make it easier to explain. It may even be required before you can
>> give a proper explanation. But forcing your
>> students/readers/conversational partners/victims to understand the
>> subtle idea as a prerequisite to understanding the thing they
>> actually want to know about is not always a winning strategy, in my
>> experience.
>
> In my experience, when that appears to be the case, you haven't really 
> understood it yourself (or perhaps you are just unwilling to face the 
> fact that what you thought was a Subtle Idea is really a Horrible Hack).
>
> http://chronicle.com/jobs/v45/i47/4547ctlyst.htm

I certainly agree that the ability to explain something in terms the
average Joe can understand is a good measure of how well one
understands something. Indeed, that was the main pain I experienced
when writing my book--the constant nagging feeling that if I could
just grok this stuff one level deeper myself, that a better, shorter,
way to explain it would just pop out.

But that doesn't mean that the best way to approach every topic is to
start from first principles. The example I'm thinking of in
particular, that came up while writing in my book, is the way Lisp
splits apart READ and EVAL, exposing both bits. Once you get that the
reader is just responsible for translating text into Lisp objects and
that the semantics of Lisp are defined in terms of Lisp objects (and
that the basic evaluation rule is pretty straight-forward) you are
well on your way to understanding a lot Lisp and the way it's the way
it is. But it's not clear how soon you want to dive down to that
level, especially when it's so foreign to folks' prior experience.

-Peter

-- 
Peter Seibel           * ·····@gigamonkeys.com
Gigamonkeys Consulting * http://www.gigamonkeys.com/
Practical Common Lisp  * http://www.gigamonkeys.com/book/
From: Ron Garret
Subject: Re: Hacking CL into a Lisp-1 (an intro to code-walking)
Date: 
Message-ID: <rNOSPAMon-D567EE.18160923042006@news.gha.chartermi.net>
In article <··············@gigamonkeys.com>,
 Peter Seibel <·····@gigamonkeys.com> wrote:

> Ron Garret <·········@flownet.com> writes:
> 
> >>   1) It is desirable to be able to FUNCALL and APPLY globally defined
> >>      functions through a symbol.
> >
> > Why?
> 
> Because it provides a level of indirection that allows code to pick up
> changes in function definitions. Consider the difference between:
> 
>   (funcall 'foo x y z)
> 
> and:
> 
>   (funcall #'foo x y z)
> 
> in the face of a redefinition of FOO.

What difference would that be?

? (defun foo () 1)
FOO
? (funcall 'foo)
1
? (funcall #'foo)
1
? (defun foo () 2)
FOO
? (funcall 'foo)
2
? (funcall #'foo)
2
? (defun baz () (funcall #'foo))
BAZ
? (baz)
2
? (defun foo () 3)
FOO
? (baz)
3
? 

Looks like the same behavior to me.


> But that doesn't mean that the best way to approach every topic is to
> start from first principles. The example I'm thinking of in
> particular, that came up while writing in my book, is the way Lisp
> splits apart READ and EVAL, exposing both bits. Once you get that the
> reader is just responsible for translating text into Lisp objects and
> that the semantics of Lisp are defined in terms of Lisp objects (and
> that the basic evaluation rule is pretty straight-forward) you are
> well on your way to understanding a lot Lisp and the way it's the way
> it is. But it's not clear how soon you want to dive down to that
> level, especially when it's so foreign to folks' prior experience.

We should probably start another thread if you really want to get into 
this.

rg
From: Bill Atkins
Subject: Re: Hacking CL into a Lisp-1 (an intro to code-walking)
Date: 
Message-ID: <87k69f4v2u.fsf@rpi.edu>
Ron Garret <·········@flownet.com> writes:

> In article <··············@gigamonkeys.com>,
>  Peter Seibel <·····@gigamonkeys.com> wrote:
>
>> Ron Garret <·········@flownet.com> writes:
>> 
>> >>   1) It is desirable to be able to FUNCALL and APPLY globally defined
>> >>      functions through a symbol.
>> >
>> > Why?
>> 
>> Because it provides a level of indirection that allows code to pick up
>> changes in function definitions. Consider the difference between:
>> 
>>   (funcall 'foo x y z)
>> 
>> and:
>> 
>>   (funcall #'foo x y z)
>> 
>> in the face of a redefinition of FOO.
>
> What difference would that be?
>
> ? (defun foo () 1)
> FOO
> ? (funcall 'foo)
> 1
> ? (funcall #'foo)
> 1
> ? (defun foo () 2)
> FOO
> ? (funcall 'foo)
> 2
> ? (funcall #'foo)
> 2
> ? (defun baz () (funcall #'foo))
> BAZ
> ? (baz)
> 2
> ? (defun foo () 3)
> FOO
> ? (baz)
> 3
> ? 
>
> Looks like the same behavior to me.

Probably because this is being interpreted.  If you were compiling
this, the (function foo) could be replaced with the actual address of
FOO, since it is known at compile-time; with just a symbol, it would
be necessary to find the function attached to FOO and then call that.
From: Peter Seibel
Subject: Re: Hacking CL into a Lisp-1 (an intro to code-walking)
Date: 
Message-ID: <m2d5f792fx.fsf@gigamonkeys.com>
Bill Atkins <············@rpi.edu> writes:

> Ron Garret <·········@flownet.com> writes:
>
>> In article <··············@gigamonkeys.com>,
>>  Peter Seibel <·····@gigamonkeys.com> wrote:
>>
>>> Ron Garret <·········@flownet.com> writes:
>>> 
>>> >>   1) It is desirable to be able to FUNCALL and APPLY globally defined
>>> >>      functions through a symbol.
>>> >
>>> > Why?
>>> 
>>> Because it provides a level of indirection that allows code to pick up
>>> changes in function definitions. Consider the difference between:
>>> 
>>>   (funcall 'foo x y z)
>>> 
>>> and:
>>> 
>>>   (funcall #'foo x y z)
>>> 
>>> in the face of a redefinition of FOO.
>>
>> What difference would that be?
>>
>> ? (defun foo () 1)
>> FOO
>> ? (funcall 'foo)
>> 1
>> ? (funcall #'foo)
>> 1
>> ? (defun foo () 2)
>> FOO
>> ? (funcall 'foo)
>> 2
>> ? (funcall #'foo)
>> 2
>> ? (defun baz () (funcall #'foo))
>> BAZ
>> ? (baz)
>> 2
>> ? (defun foo () 3)
>> FOO
>> ? (baz)
>> 3
>> ? 
>>
>> Looks like the same behavior to me.
>
> Probably because this is being interpreted.  If you were compiling
> this, the (function foo) could be replaced with the actual address of
> FOO, since it is known at compile-time; with just a symbol, it would
> be necessary to find the function attached to FOO and then call that.

Actually no, that's not the issue: (function foo) behaves just like
(foo ...) as far is how and when the current function binding is
looked up. And it has to work this way because you can compile a
function that contains either kind of reference to a not-yet-defined
function.

The issue that I was getting at, which my original example didn't
demonstrate, has to do with when you store a reference to a function
or symbol in a variable and later pass the value of that variable to
FUNCALL. (See my other recent post in this thread for a full example.)

-Peter

-- 
Peter Seibel           * ·····@gigamonkeys.com
Gigamonkeys Consulting * http://www.gigamonkeys.com/
Practical Common Lisp  * http://www.gigamonkeys.com/book/
From: Peter Seibel
Subject: Re: Hacking CL into a Lisp-1 (an intro to code-walking)
Date: 
Message-ID: <m2hd4j92kx.fsf@gigamonkeys.com>
Ron Garret <·········@flownet.com> writes:

> In article <··············@gigamonkeys.com>,
>  Peter Seibel <·····@gigamonkeys.com> wrote:
>
>> Ron Garret <·········@flownet.com> writes:
>> 
>> >>   1) It is desirable to be able to FUNCALL and APPLY globally defined
>> >>      functions through a symbol.
>> >
>> > Why?
>> 
>> Because it provides a level of indirection that allows code to pick up
>> changes in function definitions. Consider the difference between:
>> 
>>   (funcall 'foo x y z)
>> 
>> and:
>> 
>>   (funcall #'foo x y z)
>> 
>> in the face of a redefinition of FOO.
>
> What difference would that be?
>
> ? (defun foo () 1)
> FOO
> ? (funcall 'foo)
> 1
> ? (funcall #'foo)
> 1
> ? (defun foo () 2)
> FOO
> ? (funcall 'foo)
> 2
> ? (funcall #'foo)
> 2
> ? (defun baz () (funcall #'foo))
> BAZ
> ? (baz)
> 2
> ? (defun foo () 3)
> FOO
> ? (baz)
> 3
> ? 
>
> Looks like the same behavior to me.

Sorry, my example was a bit off. I was thinking of this case:

  CL-USER> (defun foo () 'first)
  FOO
  CL-USER> (defvar *foo-fn* #'foo)
  *FOO-FN*
  CL-USER> (defvar *foo-sym* 'foo)
  *FOO-SYM*
  CL-USER> (list (funcall *foo-fn*) (funcall *foo-sym*))
  (FIRST FIRST)
  CL-USER> (defun foo () 'second)
  FOO
  CL-USER> (list (funcall *foo-fn*) (funcall *foo-sym*))
  (FIRST SECOND)

-Peter

-- 
Peter Seibel           * ·····@gigamonkeys.com
Gigamonkeys Consulting * http://www.gigamonkeys.com/
Practical Common Lisp  * http://www.gigamonkeys.com/book/
From: Ron Garret
Subject: Re: Hacking CL into a Lisp-1 (an intro to code-walking)
Date: 
Message-ID: <rNOSPAMon-90A1D6.22271023042006@news.gha.chartermi.net>
In article <··············@gigamonkeys.com>,
 Peter Seibel <·····@gigamonkeys.com> wrote:

> Ron Garret <·········@flownet.com> writes:
> 
> > In article <··············@gigamonkeys.com>,
> >  Peter Seibel <·····@gigamonkeys.com> wrote:
> >
> >> Ron Garret <·········@flownet.com> writes:
> >> 
> >> >>   1) It is desirable to be able to FUNCALL and APPLY globally defined
> >> >>      functions through a symbol.
> >> >
> >> > Why?
> >> 
> >> Because it provides a level of indirection that allows code to pick up
> >> changes in function definitions. Consider the difference between:
> >> 
> >>   (funcall 'foo x y z)
> >> 
> >> and:
> >> 
> >>   (funcall #'foo x y z)
> >> 
> >> in the face of a redefinition of FOO.
> >
> > What difference would that be?
> >
> > ? (defun foo () 1)
> > FOO
> > ? (funcall 'foo)
> > 1
> > ? (funcall #'foo)
> > 1
> > ? (defun foo () 2)
> > FOO
> > ? (funcall 'foo)
> > 2
> > ? (funcall #'foo)
> > 2
> > ? (defun baz () (funcall #'foo))
> > BAZ
> > ? (baz)
> > 2
> > ? (defun foo () 3)
> > FOO
> > ? (baz)
> > 3
> > ? 
> >
> > Looks like the same behavior to me.
> 
> Sorry, my example was a bit off. I was thinking of this case:
> 
>   CL-USER> (defun foo () 'first)
>   FOO
>   CL-USER> (defvar *foo-fn* #'foo)
>   *FOO-FN*
>   CL-USER> (defvar *foo-sym* 'foo)
>   *FOO-SYM*
>   CL-USER> (list (funcall *foo-fn*) (funcall *foo-sym*))
>   (FIRST FIRST)
>   CL-USER> (defun foo () 'second)
>   FOO
>   CL-USER> (list (funcall *foo-fn*) (funcall *foo-sym*))
>   (FIRST SECOND)
> 
> -Peter

Why not just do this then?

(defvar *foo-fn* (lambda () (foo)))

rg
From: Ari Johnson
Subject: Re: Hacking CL into a Lisp-1 (an intro to code-walking)
Date: 
Message-ID: <m2r73n8rsx.fsf@hermes.theari.com>
Ron Garret <·········@flownet.com> writes:

> Why not just do this then?
>
> (defvar *foo-fn* (lambda () (foo)))

Probably because it completely misses the point, although the lack of
scalability could also be a factor.
From: Bill Atkins
Subject: Re: Hacking CL into a Lisp-1 (an intro to code-walking)
Date: 
Message-ID: <8764kztu9o.fsf@rpi.edu>
Ari Johnson <·········@gmail.com> writes:

> Ron Garret <·········@flownet.com> writes:
>
>> Why not just do this then?
>>
>> (defvar *foo-fn* (lambda () (foo)))
>
> Probably because it completely misses the point, although the lack of
> scalability could also be a factor.

In what way?
From: Ari Johnson
Subject: Re: Hacking CL into a Lisp-1 (an intro to code-walking)
Date: 
Message-ID: <m2mzeb8qgn.fsf@hermes.theari.com>
Bill Atkins <············@rpi.edu> writes:

> Ari Johnson <·········@gmail.com> writes:
>
>> Ron Garret <·········@flownet.com> writes:
>>
>>> Why not just do this then?
>>>
>>> (defvar *foo-fn* (lambda () (foo)))
>>
>> Probably because it completely misses the point, although the lack of
>> scalability could also be a factor.
>
> In what way?

Having recently written software where this kind of thing matters,
specifically where a continuously-running thread was doing the
funcalling and I wanted to change the definition of the function it
was funcalling while it kept running, I am pretty certain that a
closure stored in a global variable is not the best way to do it,
especially in lieu of feeding the function that started the
long-running thread the name of a function to call and expecting it to
call that function by name even if you change its definition.

That is, you still end up feeding the long-running thread a symbol
that names a function to funcall, it's just a matter of whether you
feed it like A or like B:

A:
(start-server :handler 'handler)

B:
(defvar *handler-function* (lambda () (handler)))
(start-server)
From: Ron Garret
Subject: Re: Hacking CL into a Lisp-1 (an intro to code-walking)
Date: 
Message-ID: <rNOSPAMon-8260CD.23054523042006@news.gha.chartermi.net>
In article <··············@hermes.theari.com>,
 Ari Johnson <·········@gmail.com> wrote:

> Bill Atkins <············@rpi.edu> writes:
> 
> > Ari Johnson <·········@gmail.com> writes:
> >
> >> Ron Garret <·········@flownet.com> writes:
> >>
> >>> Why not just do this then?
> >>>
> >>> (defvar *foo-fn* (lambda () (foo)))
> >>
> >> Probably because it completely misses the point, although the lack of
> >> scalability could also be a factor.
> >
> > In what way?
> 
> Having recently written software where this kind of thing matters,
> specifically where a continuously-running thread was doing the
> funcalling and I wanted to change the definition of the function it
> was funcalling while it kept running, I am pretty certain that a
> closure stored in a global variable is not the best way to do it,
> especially in lieu of feeding the function that started the
> long-running thread the name of a function to call and expecting it to
> call that function by name even if you change its definition.
> 
> That is, you still end up feeding the long-running thread a symbol
> that names a function to funcall, it's just a matter of whether you
> feed it like A or like B:
> 
> A:
> (start-server :handler 'handler)
> 
> B:
> (defvar *handler-function* (lambda () (handler)))
> (start-server)

C:
(start-server :handler (lambda () (handler)))

rg
From: Ari Johnson
Subject: Re: Hacking CL into a Lisp-1 (an intro to code-walking)
Date: 
Message-ID: <m2iroz8pyu.fsf@hermes.theari.com>
Ron Garret <·········@flownet.com> writes:

> In article <··············@hermes.theari.com>,
>  Ari Johnson <·········@gmail.com> wrote:
>
>> Bill Atkins <············@rpi.edu> writes:
>> 
>> > Ari Johnson <·········@gmail.com> writes:
>> >
>> >> Ron Garret <·········@flownet.com> writes:
>> >>
>> >>> Why not just do this then?
>> >>>
>> >>> (defvar *foo-fn* (lambda () (foo)))
>> >>
>> >> Probably because it completely misses the point, although the lack of
>> >> scalability could also be a factor.
>> >
>> > In what way?
>> 
>> Having recently written software where this kind of thing matters,
>> specifically where a continuously-running thread was doing the
>> funcalling and I wanted to change the definition of the function it
>> was funcalling while it kept running, I am pretty certain that a
>> closure stored in a global variable is not the best way to do it,
>> especially in lieu of feeding the function that started the
>> long-running thread the name of a function to call and expecting it to
>> call that function by name even if you change its definition.
>> 
>> That is, you still end up feeding the long-running thread a symbol
>> that names a function to funcall, it's just a matter of whether you
>> feed it like A or like B:
>> 
>> A:
>> (start-server :handler 'handler)
>> 
>> B:
>> (defvar *handler-function* (lambda () (handler)))
>> (start-server)
>
> C:
> (start-server :handler (lambda () (handler)))

Should I be surprised that you like making code harder to read?
From: Ron Garret
Subject: Re: Hacking CL into a Lisp-1 (an intro to code-walking)
Date: 
Message-ID: <rNOSPAMon-3D8013.00174924042006@news.gha.chartermi.net>
In article <··············@hermes.theari.com>,
 Ari Johnson <·········@gmail.com> wrote:

> Ron Garret <·········@flownet.com> writes:
> 
> > In article <··············@hermes.theari.com>,
> >  Ari Johnson <·········@gmail.com> wrote:
> >
> >> Bill Atkins <············@rpi.edu> writes:
> >> 
> >> > Ari Johnson <·········@gmail.com> writes:
> >> >
> >> >> Ron Garret <·········@flownet.com> writes:
> >> >>
> >> >>> Why not just do this then?
> >> >>>
> >> >>> (defvar *foo-fn* (lambda () (foo)))
> >> >>
> >> >> Probably because it completely misses the point, although the lack of
> >> >> scalability could also be a factor.
> >> >
> >> > In what way?
> >> 
> >> Having recently written software where this kind of thing matters,
> >> specifically where a continuously-running thread was doing the
> >> funcalling and I wanted to change the definition of the function it
> >> was funcalling while it kept running, I am pretty certain that a
> >> closure stored in a global variable is not the best way to do it,
> >> especially in lieu of feeding the function that started the
> >> long-running thread the name of a function to call and expecting it to
> >> call that function by name even if you change its definition.
> >> 
> >> That is, you still end up feeding the long-running thread a symbol
> >> that names a function to funcall, it's just a matter of whether you
> >> feed it like A or like B:
> >> 
> >> A:
> >> (start-server :handler 'handler)
> >> 
> >> B:
> >> (defvar *handler-function* (lambda () (handler)))
> >> (start-server)
> >
> > C:
> > (start-server :handler (lambda () (handler)))
> 
> Should I be surprised that you like making code harder to read?

I don't see why my way is any hard to read than your option B.  But if 
you really don't like having that extra lambda in there you can always 
define a reader macro so that you can type, e.g.:

(start-server :handler #"handler)

where #"foo expands to (lambda () (foo)).

rg
From: Ari Johnson
Subject: Re: Hacking CL into a Lisp-1 (an intro to code-walking)
Date: 
Message-ID: <m2acab80le.fsf@hermes.theari.com>
Ron Garret <·········@flownet.com> writes:

> In article <··············@hermes.theari.com>,
>  Ari Johnson <·········@gmail.com> wrote:
>
>> Ron Garret <·········@flownet.com> writes:
>> 
>> > In article <··············@hermes.theari.com>,
>> >  Ari Johnson <·········@gmail.com> wrote:
>> >
>> >> Bill Atkins <············@rpi.edu> writes:
>> >> 
>> >> > Ari Johnson <·········@gmail.com> writes:
>> >> >
>> >> >> Ron Garret <·········@flownet.com> writes:
>> >> >>
>> >> >>> Why not just do this then?
>> >> >>>
>> >> >>> (defvar *foo-fn* (lambda () (foo)))
>> >> >>
>> >> >> Probably because it completely misses the point, although the lack of
>> >> >> scalability could also be a factor.
>> >> >
>> >> > In what way?
>> >> 
>> >> Having recently written software where this kind of thing matters,
>> >> specifically where a continuously-running thread was doing the
>> >> funcalling and I wanted to change the definition of the function it
>> >> was funcalling while it kept running, I am pretty certain that a
>> >> closure stored in a global variable is not the best way to do it,
>> >> especially in lieu of feeding the function that started the
>> >> long-running thread the name of a function to call and expecting it to
>> >> call that function by name even if you change its definition.
>> >> 
>> >> That is, you still end up feeding the long-running thread a symbol
>> >> that names a function to funcall, it's just a matter of whether you
>> >> feed it like A or like B:
>> >> 
>> >> A:
>> >> (start-server :handler 'handler)
>> >> 
>> >> B:
>> >> (defvar *handler-function* (lambda () (handler)))
>> >> (start-server)
>> >
>> > C:
>> > (start-server :handler (lambda () (handler)))
>> 
>> Should I be surprised that you like making code harder to read?
>
> I don't see why my way is any hard to read than your option B.  But if 
> you really don't like having that extra lambda in there you can always 
> define a reader macro so that you can type, e.g.:
>
> (start-server :handler #"handler)
>
> where #"foo expands to (lambda () (foo)).

Or, in the alternative, I can just write 'handler.  Is there a reason
you are opposed to doing things the easy way?
From: Pascal Bourguignon
Subject: Re: Hacking CL into a Lisp-1 (an intro to code-walking)
Date: 
Message-ID: <87d5f9xekt.fsf@thalassa.informatimago.com>
Peter Seibel <·····@gigamonkeys.com> writes:

>> Nyms is not an english word as far as I can determine. (Remember,
>> we're talking about pedagogy here, so this is not a trivial detail.)
>
> I'm sorry if you didn't get the joke and doubly sorry if it actually
> confused you. Humour is always a tricky thing, but it can be a useful
> pedagogical tool. (Helps keep the student from falling asleep,
> drooling on your book, and getting the pages stuck to their face.)

It's only that nym is spelled name in English (nom in French, etc),
but it's still the same word.

-- 
__Pascal Bourguignon__                     http://www.informatimago.com/

NOTE: The most fundamental particles in this product are held
together by a "gluing" force about which little is currently known
and whose adhesive power can therefore not be permanently
guaranteed.
From: Kalle Olavi Niemitalo
Subject: Re: Hacking CL into a Lisp-1 (an intro to code-walking)
Date: 
Message-ID: <8764l0j0es.fsf@Astalo.kon.iki.fi>
Ron Garret <·········@flownet.com> writes:

> ? (defun (setf foo) () t)
> (SETF FOO)
> ? ((setf foo))
> Error: Car of ((SETF FOO)) is not a function name or lambda-expression.

CLISP returns T here, as an extension.
http://clisp.cons.org/impnotes.html#function-form
From: David Sletten
Subject: Re: Hacking CL into a Lisp-1 (an intro to code-walking)
Date: 
Message-ID: <DsI1g.5524$WA3.2807@tornado.socal.rr.com>
Hoan Ton-That wrote:


> ;; We can also define the Y combinator in Lisp-1 style, just for fun:
> (defun1 Y (f)
>   ((lambda (x)
>      (f (lambda (y) ((x x) y))))
>    (lambda (x)
>      (f (lambda (y) ((x x) y))))))
> 
> ;; As opposed the the very verbose Lisp-2 style:
> (defun Y (f)
>   (funcall #'(lambda (x)
> 	       (funcall f #'(lambda (y) (funcall (funcall x x) y))))
> 	   #'(lambda (x)
> 	       (funcall f #'(lambda (y) (funcall (funcall x x) y))))))
> 

This is a trivial issue, but you don't need the first FUNCALL:
(defun Y (f)
   ((lambda (x)
      (funcall f #'(lambda (y) (funcall (funcall x x) y))))
    #'(lambda (x)
        (funcall f #'(lambda (y) (funcall (funcall x x) y))))))

Aloha,
David Sletten
From: Hoan Ton-That
Subject: Re: Hacking CL into a Lisp-1 (an intro to code-walking)
Date: 
Message-ID: <1145530526.446480.172390@j33g2000cwa.googlegroups.com>
Yes, yes...

One of the wierd things about CL is that you can't have:

(#'(lambda (x) x) 'x)

The caar of the form must be 'lambda.  So its not immediately
obvious that you can drop funcall, especially when lots of
people unneccesarily sharp-quote their lambdas...
From: David Sletten
Subject: Re: Hacking CL into a Lisp-1 (an intro to code-walking)
Date: 
Message-ID: <pmQ1g.5753$543.3116@tornado.socal.rr.com>
Hoan Ton-That wrote:

> Yes, yes...
> 
> One of the wierd things about CL is that you can't have:
> 
> (#'(lambda (x) x) 'x)
> 
> The caar of the form must be 'lambda.  So its not immediately
> obvious that you can drop funcall, especially when lots of
> people unneccesarily sharp-quote their lambdas...
> 
Well let's be clear, there is no unnecessary quoting of lambdas. The 
sharp-quote notation is syntactic sugar for the FUNCTION special 
operator, which is required to create a closure from a lambda 
expression. It just so happens that Common Lisp also has a LAMBDA macro 
which provides a syntactic shortcut for this same operation, but this 
doesn't change the fundamental underlying use of FUNCTION (or sharp-quote).

LAMBDA is serving 2 different roles here:
((lambda (x) (* x 9)) 3) ;Lambda expression applied to arg 3
(mapcar (lambda (l) (first l)) '((a b) (c d) (e f))) ;LAMBDA macro 
equivalent to...
(mapcar #'(lambda (l) (first l)) '((a b) (c d) (e f))) ;FUNCTION (#') 
applied to lambda expression

Aloha,
David Sletten
From: Thomas F. Burdick
Subject: Re: Hacking CL into a Lisp-1 (an intro to code-walking)
Date: 
Message-ID: <xcv8xpzjdzo.fsf@conquest.OCF.Berkeley.EDU>
David Sletten <·····@slytobias.com> writes:

> Hoan Ton-That wrote:
> 
> > Yes, yes...
> > One of the wierd things about CL is that you can't have:
> > (#'(lambda (x) x) 'x)
> > The caar of the form must be 'lambda.  So its not immediately
> > obvious that you can drop funcall, especially when lots of
> > people unneccesarily sharp-quote their lambdas...
> >
> Well let's be clear, there is no unnecessary quoting of lambdas. The
> sharp-quote notation is syntactic sugar for the FUNCTION special
> operator, which is required to create a closure from a lambda
> expression. It just so happens that Common Lisp also has a LAMBDA
> macro which provides a syntactic shortcut for this same operation, but
> this doesn't change the fundamental underlying use of FUNCTION (or
> sharp-quote).

Thus making the sharp-quote unnecessary.  The LAMBDA macro expands
into something that evaluates to a function -- no need to write out
its macroexpansion any more than there is for PUSH.

-- 
           /|_     .-----------------------.                        
         ,'  .\  / | Free Mumia Abu-Jamal! |
     ,--'    _,'   | Abolish the racist    |
    /       /      | death penalty!        |
   (   -.  |       `-----------------------'
   |     ) |                               
  (`-.  '--.)                              
   `. )----'                               
From: David Sletten
Subject: Re: Hacking CL into a Lisp-1 (an intro to code-walking)
Date: 
Message-ID: <co92g.6066$WA3.5653@tornado.socal.rr.com>
Thomas F. Burdick wrote:

> David Sletten <·····@slytobias.com> writes:
> 
> 
>>Hoan Ton-That wrote:
>>
>>
>>>Yes, yes...
>>>One of the wierd things about CL is that you can't have:
>>>(#'(lambda (x) x) 'x)
>>>The caar of the form must be 'lambda.  So its not immediately
>>>obvious that you can drop funcall, especially when lots of
>>>people unneccesarily sharp-quote their lambdas...
>>>
>>
>>Well let's be clear, there is no unnecessary quoting of lambdas. The
>>sharp-quote notation is syntactic sugar for the FUNCTION special
>>operator, which is required to create a closure from a lambda
>>expression. It just so happens that Common Lisp also has a LAMBDA
>>macro which provides a syntactic shortcut for this same operation, but
>>this doesn't change the fundamental underlying use of FUNCTION (or
>>sharp-quote).
> 
> 
> Thus making the sharp-quote unnecessary.  The LAMBDA macro expands
> into something that evaluates to a function -- no need to write out
> its macroexpansion any more than there is for PUSH.
> 

As I made clear in my post, there is _fundamentally_ no unnecessary 
sharp-quoting--either you do it or Lisp does it. I was trying to clarify 
for the OP the potentially confusing dual use of LAMBDA. Considering 
that my post already contained all of the information content of your 
response, what is it that you think you are accomplishing with your 
stylistic quibble?

David Sletten