From: Ron Garret
Subject: An alternative to Lisp-2
Date: 
Message-ID: <rNOSPAMon-7EC768.08191102052006@news.gha.chartermi.net>
Lisp-2 is a hacky but workable solution to the problem of unintended 
name capture in macros.  But as

http://www.nhplace.com/kent/Papers/Technical-Issues.html

points out it is an incomplete solution, as free function calls can 
still be shadowed by FLET or LABELS (though this is a minor problem in 
practice).  The above paper suggests `(FUNCALL ',#'FOO ...) as a 
substitute for (FOO ...) in macros as an ironclad guarantee against 
unintentional name capture.

Which got me to thinking...

Suppose this were legal:

(#'FOO ...)

Now we could write macros like:

(defmacro frob (blitz)
  `(,#'list ',blitz (snozbar)))

and it would still work as expected if someone did:

(defun foo (list) (frob list))

And this would work too:

(defun foo (...) ...)
(defmacro m1 (...) `(... (,#'foo ...) ...))

(defun baz () (flet ((foo (...) ...)) (m1 ...))

So this is a BETTER solution than Lisp-2 because it not only avoids 
unintentional name capture through lexical value bindings, but also 
unintentional capture through function bindings as well.

Which would seem like a Good Thing.

But if we're going to do that we don't need Lisp-2 any more!  All we 
need is some way to unconditionally refer to the GLOBAL binding of a 
symbol!  Suppose we had a special form (global foo) analogous to 
(function foo) with reader syntax, say, #^foo analagous to #'foo.  Now 
we could write in a Lisp-1:

(defmacro frob (blitz)
  `(,#^list ',blitz (snozbar)))

and (defun foo (list) (frob list)) would work as expected.

This approach solves another problem as well.  In the macro M1 above, if 
FOO is redefined we have to recompile M1 in order to pick up the new 
definition of FOO.  But now we can fix that by writing:

(defmacro m1 (...) `(... (#^foo ...) ...))

Note that the comma has disappeared.

The upshot, it seems to me, is the best of both worlds: the simplicity 
of a Lisp-1 with the ease of macro writing of a Lisp-2.  The only thing 
you have to remember is that to invoke a function inside a macro 
expansion (NOTE: not macro CODE, just the expansion) you have to write 
(#^foo ...) instead of just (foo ...), but this seems to be no more of a 
burden than remembering where to use #' and FUNCALL in a Lisp-2.  
Furthermore, #^ would generally be used ONLY in macros, and not anywhere 
else [1].  Since macros tend to be used only by more advanced 
programmers, this would tend to hide whatever ugliness remained from new 
programmers until they were more mentally prepared to deal with it.

My question is: would this work?  Are there drawbacks that I have 
overlooked?

rg

[1] The one exception being the classic case of using LIST as a 
parameter name, where you would now have to write:

(defun foo (list) (#^list list))

if you wanted to invoke the built-in LIST function.

From: ·······@gmail.com
Subject: Re: An alternative to Lisp-1 (Was: An alternative to Lisp-2)
Date: 
Message-ID: <1146587309.628435.264860@j33g2000cwa.googlegroups.com>
Ron Garret wrote:
> Lisp-2 is a hacky but workable solution to the problem of unintended
> name capture in macros.  But as
>
> http://www.nhplace.com/kent/Papers/Technical-Issues.html
>
> points out it is an incomplete solution, as free function calls can
> still be shadowed by FLET or LABELS (though this is a minor problem in
> practice).  The above paper suggests `(FUNCALL ',#'FOO ...) as a
> substitute for (FOO ...) in macros as an ironclad guarantee against
> unintentional name capture.
>
> Which got me to thinking...
>
> Suppose this were legal:
>
> (#'FOO ...)
>
> Now we could write macros like:
[...]
> So this is a BETTER solution than Lisp-2 because it not only avoids
> unintentional name capture through lexical value bindings, but also
> unintentional capture through function bindings as well.
>
> Which would seem like a Good Thing.
>
> But if we're going to do that we don't need Lisp-2 any more!  All we
> need is some way to unconditionally refer to the GLOBAL binding of a
> symbol!  Suppose we had a special form (global foo) analogous to
> (function foo) with reader syntax, say, #^foo analagous to #'foo.  Now
> we could write in a Lisp-1:
>
> (defmacro frob (blitz)
>   `(,#^list ',blitz (snozbar)))

(Thank you for actually thinking and trying to find doable fixes [as
opposed to just deciding to go and make a new language])

This solve the problem of accidental capture but only at the cost of a
lot of typing and thinking overhead, and not just in macros either. I
regularly use list, car, lambda as variable names, and frequently use
the same name for a function and the variable that holds one of its
return values.

Here's my suggestion to make lisp-2s more HoF friendly: Add a way to
specify that certain arguments in a given lambda list refer to the
lexical (unless it's declared dynamic, I suppose) binding of the
function of that name, instead of that of the value of that name.

Something like
(defun HoF (#'fun arg)
  (and (eq (fun arg)
               (funcall 'fun arg))
         (eq (fun arg)
               (funcall #'fun arg))))

=> T

would expand into

(defun HoF (fun args)
  (flet ((fun (&rest args) (apply fun args)))
    (and (eq (fun arg)
                 (funcall 'fun arg)) ;; careful here
           (eq (fun arg)
                 (funcall #'fun arg)))))

Macrolet might be better than flet. Performance-wise, it certainly is.
However, it violates least-surprise for #'fun. On the other hand, flet
seems like it might violate the same principle for 'fun.

I chose #' instead of &foo because I think it meshes better with the
rest of the & keywords. For example:

(defun HoF2 (&optional (#'fun #'id) &rest args)
   (apply fun args))

While I'm not discounting the usefulness of the GLOBAL reader-macro for
better hygiene (nor that of scheme macros when there is more rewriting
than computing), it seems to me that #' lambda arguments makes lisp-2s
nearly as HoF friendly as lisp-1s. In fact, some might prefer the way
the intent to use an argument as a function is explicited; I'm not sure
it's that useful, but I guess it can be nice.

Paul Khuong

PS, no code, but i think it's mostly a matter of rewriting the lambda &
defun/macro/generic macros. Once that is done, code walkers should be
able to do their job with regular CL lambda lists.
From: Ron Garret
Subject: Re: An alternative to Lisp-1 (Was: An alternative to Lisp-2)
Date: 
Message-ID: <rNOSPAMon-193500.10351502052006@news.gha.chartermi.net>
In article <························@j33g2000cwa.googlegroups.com>,
 ·······@gmail.com wrote:

> (Thank you for actually thinking and trying to find doable fixes [as
> opposed to just deciding to go and make a new language])

Well, I may yet end up with a new language when all is said and done ;-)  
But I do try to think.

> This solve the problem of accidental capture but only at the cost of a
> lot of typing and thinking overhead, and not just in macros either. I
> regularly use list, car, lambda as variable names, and frequently use
> the same name for a function and the variable that holds one of its
> return values.

Personally, I consider it a feature that my idea might discourage such 
coding practices.

> Here's my suggestion to make lisp-2s more HoF friendly: Add a way to
> specify that certain arguments in a given lambda list refer to the
> lexical (unless it's declared dynamic, I suppose) binding of the
> function of that name, instead of that of the value of that name.
> 
> Something like
> (defun HoF (#'fun arg)
>   (and (eq (fun arg)
>                (funcall 'fun arg))
>          (eq (fun arg)
>                (funcall #'fun arg))))
> 
> => T
> 
> would expand into
> 
> (defun HoF (fun args)
>   (flet ((fun (&rest args) (apply fun args)))
>     (and (eq (fun arg)
>                  (funcall 'fun arg)) ;; careful here
>            (eq (fun arg)
>                  (funcall #'fun arg)))))
> 
> Macrolet might be better than flet. Performance-wise, it certainly is.
> However, it violates least-surprise for #'fun. On the other hand, flet
> seems like it might violate the same principle for 'fun.
> 
> I chose #' instead of &foo because I think it meshes better with the
> rest of the & keywords. For example:
> 
> (defun HoF2 (&optional (#'fun #'id) &rest args)
>    (apply fun args))
> 
> While I'm not discounting the usefulness of the GLOBAL reader-macro for
> better hygiene (nor that of scheme macros when there is more rewriting
> than computing), it seems to me that #' lambda arguments makes lisp-2s
> nearly as HoF friendly as lisp-1s. In fact, some might prefer the way
> the intent to use an argument as a function is explicited; I'm not sure
> it's that useful, but I guess it can be nice.
> 
> Paul Khuong
> 
> PS, no code, but i think it's mostly a matter of rewriting the lambda &
> defun/macro/generic macros. Once that is done, code walkers should be
> able to do their job with regular CL lambda lists.

Not a bad idea, but the problem is that you need to redefined ALL of 
CL's binding constructs to make it work in a seamless way.  That can 
become a real hassle.

Personally, the direction I'm going is to unify everything into a single 
BIND construct that combines LET (and FLET since I'm tending towards 
Lisp-1), multiple-value-let, and destructuring-bind, and also does away 
with special declarations, e.g.:

(bind ((x 1)                  ; The usual thing
       ((values x y) ...)     ; multiple-value-bind
       ((symbol-value x) ...) ; like LET with a special declaration
       ((x (y) z) ...)        ; like destructuring-bind
      ) ...)

VALUES and SYMBOL-VALUE become semi-reserved words, and cannot be bound 
as the first variable in a destructuring-bind construct.

Then you just have to worry about LAMBDA.

rg
From: Don Geddis
Subject: Re: An alternative to Lisp-1
Date: 
Message-ID: <87ac9zf3r9.fsf@geddis.org>
Ron Garret <·········@flownet.com> wrote on Tue, 02 May 2006:
> Personally, the direction I'm going is to unify everything into a single 
> BIND construct that combines LET (and FLET since I'm tending towards 
> Lisp-1), multiple-value-let, and destructuring-bind, and also does away 
> with special declarations, e.g.:
> (bind ((x 1)                  ; The usual thing
>        ((values x y) ...)     ; multiple-value-bind
>        ((symbol-value x) ...) ; like LET with a special declaration
>        ((x (y) z) ...)        ; like destructuring-bind
>       ) ...)

I kind of like this idea.  A simple, yet powerful, general construct.
Not bad, not bad at all.

        -- Don
_______________________________________________________________________________
Don Geddis                  http://don.geddis.org/               ···@geddis.org
Well done.  You'll make an exemplary FOOD ANIMAL.
From: Kaz Kylheku
Subject: Re: An alternative to Lisp-1
Date: 
Message-ID: <1146677811.754052.30270@i39g2000cwa.googlegroups.com>
Don Geddis wrote:
> Ron Garret <·········@flownet.com> wrote on Tue, 02 May 2006:
> > Personally, the direction I'm going is to unify everything into a single
> > BIND construct that combines LET (and FLET since I'm tending towards
> > Lisp-1), multiple-value-let, and destructuring-bind, and also does away
> > with special declarations, e.g.:
> > (bind ((x 1)                  ; The usual thing
> >        ((values x y) ...)     ; multiple-value-bind
> >        ((symbol-value x) ...) ; like LET with a special declaration
> >        ((x (y) z) ...)        ; like destructuring-bind
> >       ) ...)
>
> I kind of like this idea.  A simple, yet powerful, general construct.
> Not bad, not bad at all.

Hmm, "declaration follows use". Gee, where have I seen that before?

   int (*x[3])(); /* declare */

   (*x[0])(); /* call */

Hee hee.
From: Ron Garret
Subject: Re: An alternative to Lisp-1
Date: 
Message-ID: <rNOSPAMon-5D36DD.13502903052006@news.gha.chartermi.net>
In article <·······················@i39g2000cwa.googlegroups.com>,
 "Kaz Kylheku" <········@gmail.com> wrote:

> Don Geddis wrote:
> > Ron Garret <·········@flownet.com> wrote on Tue, 02 May 2006:
> > > Personally, the direction I'm going is to unify everything into a single
> > > BIND construct that combines LET (and FLET since I'm tending towards
> > > Lisp-1), multiple-value-let, and destructuring-bind, and also does away
> > > with special declarations, e.g.:
> > > (bind ((x 1)                  ; The usual thing
> > >        ((values x y) ...)     ; multiple-value-bind
> > >        ((symbol-value x) ...) ; like LET with a special declaration
> > >        ((x (y) z) ...)        ; like destructuring-bind
> > >       ) ...)
> >
> > I kind of like this idea.  A simple, yet powerful, general construct.
> > Not bad, not bad at all.
> 
> Hmm, "declaration follows use". Gee, where have I seen that before?
> 
>    int (*x[3])(); /* declare */
> 
>    (*x[0])(); /* call */
> 
> Hee hee.

Huh?

rg
From: Burton Samograd
Subject: Re: An alternative to Lisp-1
Date: 
Message-ID: <87veslwo39.fsf@gmail.com>
Ron Garret <·········@flownet.com> writes:

>> Hmm, "declaration follows use". Gee, where have I seen that before?
>> 
>>    int (*x[3])(); /* declare */
>> 
>>    (*x[0])(); /* call */
>> 
>> Hee hee.
>
> Huh?

That was the motto of C variable definitions: 'declaration follows use'.

-- 
burton samograd					kruhft .at. gmail
kruhft.blogspot.com	www.myspace.com/kruhft	metashell.blogspot.com
From: Ron Garret
Subject: Re: An alternative to Lisp-1
Date: 
Message-ID: <rNOSPAMon-C6D63E.13331804052006@news.gha.chartermi.net>
In article <··············@gmail.com>,
 Burton Samograd <············@gmail.com> wrote:

> Ron Garret <·········@flownet.com> writes:
> 
> >> Hmm, "declaration follows use". Gee, where have I seen that before?
> >> 
> >>    int (*x[3])(); /* declare */
> >> 
> >>    (*x[0])(); /* call */
> >> 
> >> Hee hee.
> >
> > Huh?
> 
> That was the motto of C variable definitions: 'declaration follows use'.

Ah.  Different sense of "follows" than what I thought.

So in light of that I think two things are worth noting:

1.  VALUES is SETFable.

2.  In CL, declaration can literally follow (as opposed to precede) use:

(defun f (x &optional (y x)) (declare (fixnum x)) y)

rg
From: Kaz Kylheku
Subject: Re: An alternative to Lisp-1
Date: 
Message-ID: <1146778517.973619.293010@e56g2000cwe.googlegroups.com>
Burton Samograd wrote:
> Ron Garret <·········@flownet.com> writes:
>
> >> Hmm, "declaration follows use". Gee, where have I seen that before?
> >>
> >>    int (*x[3])(); /* declare */
> >>
> >>    (*x[0])(); /* call */
> >>
> >> Hee hee.
> >
> > Huh?
>
> That was the motto of C variable definitions: 'declaration follows use'.

Actually, it might be wortwhile to consider the implications of
applying that idea quite literally.  The use of X is denoted X, and the
binding syntax is (X <expr>).   This extends nicely. Producing multiple
values is (values x y z), so the binding is ((values x y z) (expr)).
But if destructuring is implemented simply as ((a (b c)d ) expr), the
pattern breaks! Because the object isn't produced by such an
expression. If you wanted to produce something that looks like (a (b c)
d), you would actually write `(,a (,b ,c) ,d).  So a "binding follows
use" syntax for destructuring would use the backquote.

So for instance:

  (let ((x x) ((values a b c) (values a b c)) (`(,d (,e ,f)) `(,d (,e
,f)))) ...)

rebinds x to x, a to a, and so on. By using the backquote template for
destructuring, you eliminate the ambiguities. For instance the syntax
((values a b c) ...) could otherwise be a destructuring pattern, in
which VALUES just stands for a variable. Not so if the backquote is
used for denoting destructuring patterns.

Of course, the binder has to understand how to grok the backquote
object. Since they both come from the same implementation, that is'nt a
problem. Note that the backquote occurs in a non-evaluating context, so
the unquoted variable symbols stay in the backquote expansion
somewhere.
From: Ron Garret
Subject: Re: An alternative to Lisp-1
Date: 
Message-ID: <rNOSPAMon-E401A7.15570404052006@news.gha.chartermi.net>
In article <························@e56g2000cwe.googlegroups.com>,
 "Kaz Kylheku" <········@gmail.com> wrote:

> Burton Samograd wrote:
> > Ron Garret <·········@flownet.com> writes:
> >
> > >> Hmm, "declaration follows use". Gee, where have I seen that before?
> > >>
> > >>    int (*x[3])(); /* declare */
> > >>
> > >>    (*x[0])(); /* call */
> > >>
> > >> Hee hee.
> > >
> > > Huh?
> >
> > That was the motto of C variable definitions: 'declaration follows use'.
> 
> Actually, it might be wortwhile to consider the implications of
> applying that idea quite literally.  The use of X is denoted X, and the
> binding syntax is (X <expr>).   This extends nicely. Producing multiple
> values is (values x y z), so the binding is ((values x y z) (expr)).
> But if destructuring is implemented simply as ((a (b c)d ) expr), the
> pattern breaks! Because the object isn't produced by such an
> expression. If you wanted to produce something that looks like (a (b c)
> d), you would actually write `(,a (,b ,c) ,d).  So a "binding follows
> use" syntax for destructuring would use the backquote.
> 
> So for instance:
> 
>   (let ((x x) ((values a b c) (values a b c)) (`(,d (,e ,f)) `(,d (,e
> ,f)))) ...)
> 
> rebinds x to x, a to a, and so on. By using the backquote template for
> destructuring, you eliminate the ambiguities.

Only one problem: backquote is a reader macro whose behavior is not 
specified with precision.  `(,a ,b) could yield (list a b) or (cons a 
(cons b nil)) or (list* a (list* b nil)) or a dozen other things.  By 
the time the binding macro sees it, the backquote has gone away and all 
you are left with is a form starting with CONS or LIST or LIST* (or 
something else) and you're back to the same problem: you now can't use 
that symbol as the first variable in a destructuring bind clause.

The only way around this is to add another level of parens to 
distinguish destrucuture bind clauses.  But I think that gets awfully 
parenthesis-heavy even for a hard-core Lisper.  IMHO setting aside 
VALUES and SYMBOL-VALUE (and FUNCTION if you're a LISP-2 fan) as 
reserved words in binding clauses is a good compromise between 
flexibility and succinctness.

rg
From: Bill Atkins
Subject: Re: An alternative to Lisp-1
Date: 
Message-ID: <87odydpmq5.fsf@rpi.edu>
Burton Samograd <············@gmail.com> writes:

> Ron Garret <·········@flownet.com> writes:
>
>>> Hmm, "declaration follows use". Gee, where have I seen that before?
>>> 
>>>    int (*x[3])(); /* declare */
>>> 
>>>    (*x[0])(); /* call */
>>> 
>>> Hee hee.
>>
>> Huh?
>
> That was the motto of C variable definitions: 'declaration follows use'.
>
> -- 
> burton samograd					kruhft .at. gmail
> kruhft.blogspot.com	www.myspace.com/kruhft	metashell.blogspot.com

I don't understand what's going on.  Wouldn't "declaration follows
use" be:

  x = 0;
  int x;

which is obviously not C?

-- 
This is a song that took me ten years to live and two years to write.
 - Bob Dylan
From: Burton Samograd
Subject: Re: An alternative to Lisp-1
Date: 
Message-ID: <874q05454d.fsf@gmail.com>
Bill Atkins <············@rpi.edu> writes:

> I don't understand what's going on.  Wouldn't "declaration follows
> use" be:
>
>   x = 0;
>   int x;
>
> which is obviously not C?

how about "the code that you write to use a variable should be similar
to the way that it was declared in the code before it".

ie.  you make the variable definition look like the way it will be
used.

hopefully that's more clear, or else you're just screwing with me ;-) 

-- 
burton samograd					kruhft .at. gmail
kruhft.blogspot.com	www.myspace.com/kruhft	metashell.blogspot.com
From: Bill Atkins
Subject: Re: An alternative to Lisp-1
Date: 
Message-ID: <87odydb56d.fsf@rpi.edu>
Burton Samograd <············@gmail.com> writes:

> Bill Atkins <············@rpi.edu> writes:
>
>> I don't understand what's going on.  Wouldn't "declaration follows
>> use" be:
>>
>>   x = 0;
>>   int x;
>>
>> which is obviously not C?
>
> how about "the code that you write to use a variable should be similar
> to the way that it was declared in the code before it".
>
> ie.  you make the variable definition look like the way it will be
> used.

Ah.

> hopefully that's more clear, or else you're just screwing with me ;-) 

No, I was genuninely confused. :)

> -- 
> burton samograd					kruhft .at. gmail
> kruhft.blogspot.com	www.myspace.com/kruhft	metashell.blogspot.com

-- 
This is a song that took me ten years to live and two years to write.
 - Bob Dylan
From: Michael Livshin
Subject: Re: An alternative to Lisp-1
Date: 
Message-ID: <87wtd1scaz.fsf@colinux.pc-mlivshin-ibm.cadence.com.cmm>
Bill Atkins <············@rpi.edu> writes:

> Burton Samograd <············@gmail.com> writes:
>
>> That was the motto of C variable definitions: 'declaration follows use'.
>
> I don't understand what's going on.  Wouldn't "declaration follows
> use" be:
>
>   x = 0;
>   int x;
>
> which is obviously not C?

I'm starting to suspect that this usage of "follows" discriminates
against native English speakers.  go figure.

to stay on topic: I find Ron's macro problematic because it won't let
me bind multiple values if the first binding is named VALUES.  oh
wait, he's willing to impose a Lisp-1 naming discipline on himself,
right?  good for him, then.

anyway, my "super-bind" macro (doesn't everyone have one, I wonder?)
is more Lisp-N friendly:

(lette (:value (let 1)
        :values ((destructuring-bind values let* list) (values 1 2 3 4))
        :destructure ((defun (&rest args) &rest body)
                      `(defun (,values ,destructuring-bind) 
                         ,let* stuff))
        :gensym like-this
        :file (input "/dev/null" :direction :input))
  ...)

the expander dispatches on the keywords (which can be any symbols, of
cause).  :VALUE can be omitted, :VALUES likewise.

can't say I use it much, though.

cheers,
--m
From: Ron Garret
Subject: Re: An alternative to Lisp-1
Date: 
Message-ID: <rNOSPAMon-DD066E.16151404052006@news.gha.chartermi.net>
In article <··············@colinux.pc-mlivshin-ibm.cadence.com.cmm>,
 Michael Livshin <······@cmm.kakpryg.net> wrote:

> to stay on topic: I find Ron's macro problematic because it won't let
> me bind multiple values if the first binding is named VALUES.

Sure it will.  What it won't let you do is a destructure-bind the CAR of 
an expression to a variable named VALUES (or SYMBOL-VALUE).  IMO this is 
a small price to pay for succinctness.

rg
From: Ron Garret
Subject: Re: An alternative to Lisp-1
Date: 
Message-ID: <rNOSPAMon-C30540.23574204052006@news.gha.chartermi.net>
In article <·······························@news.gha.chartermi.net>,
 Ron Garret <·········@flownet.com> wrote:

> In article <··············@colinux.pc-mlivshin-ibm.cadence.com.cmm>,
>  Michael Livshin <······@cmm.kakpryg.net> wrote:
> 
> > to stay on topic: I find Ron's macro problematic because it won't let
> > me bind multiple values if the first binding is named VALUES.
> 
> Sure it will.  What it won't let you do is a destructure-bind the CAR of 
> an expression to a variable named VALUES (or SYMBOL-VALUE).  IMO this is 
> a small price to pay for succinctness.

And if you don't agree, you can use :values and :symbol-value instead.

rg
From: Pascal Costanza
Subject: Re: An alternative to Lisp-1
Date: 
Message-ID: <4bs7i6F12ljefU1@individual.net>
Don Geddis wrote:
> Ron Garret <·········@flownet.com> wrote on Tue, 02 May 2006:
>> Personally, the direction I'm going is to unify everything into a single 
>> BIND construct that combines LET (and FLET since I'm tending towards 
>> Lisp-1), multiple-value-let, and destructuring-bind, and also does away 
>> with special declarations, e.g.:
>> (bind ((x 1)                  ; The usual thing
>>        ((values x y) ...)     ; multiple-value-bind
>>        ((symbol-value x) ...) ; like LET with a special declaration
>>        ((x (y) z) ...)        ; like destructuring-bind
>>       ) ...)
> 
> I kind of like this idea.  A simple, yet powerful, general construct.
> Not bad, not bad at all.

Something like this?

http://www.geocities.com/mparker762/with.html


Pascal


-- 
3rd European Lisp Workshop
July 3-4 - Nantes, France - co-located with ECOOP 2006
http://lisp-ecoop06.bknr.net/
From: Kaz Kylheku
Subject: Re: An alternative to Lisp-1 (Was: An alternative to Lisp-2)
Date: 
Message-ID: <1146592649.004737.53190@j33g2000cwa.googlegroups.com>
·······@gmail.com wrote:
> Here's my suggestion to make lisp-2s more HoF friendly: Add a way to
> specify that certain arguments in a given lambda list refer to the
> lexical (unless it's declared dynamic, I suppose) binding of the
> function of that name, instead of that of the value of that name.
>
> Something like
> (defun HoF (#'fun arg)
>   (and (eq (fun arg)
>                (funcall 'fun arg))
>          (eq (fun arg)
>                (funcall #'fun arg))))
>
> => T
>
> would expand into
>
> (defun HoF (fun args)
>   (flet ((fun (&rest args) (apply fun args)))
>     (and (eq (fun arg)
>                  (funcall 'fun arg)) ;; careful here
>            (eq (fun arg)
>                  (funcall #'fun arg)))))

Why the complication? All you need is a way to annotate a lambda
parameter as being a function. The argument value, which must be a
function object, is then received into the function not as a variable
binding, but as a lexical function binding.

In general, the syntax (FUNCTION SYMBOL) could be used as a name
denoting the function binding of symbol. That is to say, it coul dbe
supported in all binding constructs, such as:

  ;; bind X as function name to #'FOO function.

  (let (((function x) #'foo)) (x 42)) ;; call (foo 42)

The syntax

  (let ((function x))

would have the ordinary meaning; the init form would never be optional
when (function sym) is used.

Similarly (function class), in the place of a specializable parameter
in a method lambda list, would still have the ordinary  meaning of an
object called FUNCTION of class CLASS. To write a function-bound
parameter, the spelling owuld be  ((function foo) function).
From: Emilio Lopes
Subject: Re: An alternative to Lisp-1
Date: 
Message-ID: <9sd5eqt4sn.fsf@freenet.de>
pkhuong  writes:

> Ron Garret wrote:
>> [...]

>> (defmacro frob (blitz)
>> `(,#^list ',blitz (snozbar)))

> [...]

> Here's my suggestion to make lisp-2s more HoF friendly: Add a way to
> specify that certain arguments in a given lambda list refer to the
> lexical (unless it's declared dynamic, I suppose) binding of the
> function of that name, instead of that of the value of that name.

Do you guys know Clinger's explicit renaming macros?

   Hygienic macros through explicit renaming
   William Clinger
   Lisp Pointers IV(4), 25-28, December 1991.
From: William D Clinger
Subject: Re: An alternative to Lisp-1
Date: 
Message-ID: <1147118308.369285.101960@g10g2000cwb.googlegroups.com>
Emilio Lopes wrote:
> Do you guys know Clinger's explicit renaming macros?
>
>    Hygienic macros through explicit renaming
>    William Clinger
>    Lisp Pointers IV(4), 25-28, December 1991.

That's just a tutorial paper, and a pretty old one at that.
For a more modern and technical presentation, complete
with implementation and discussion, see

André van Tonder.  SRFI 72: Simple Hygienic Macros.
http://srfi.schemers.org/srfi-72/

Will
From: Ron Garret
Subject: Re: An alternative to Lisp-1
Date: 
Message-ID: <rNOSPAMon-18F21F.12014114052006@news.gha.chartermi.net>
In article <························@g10g2000cwb.googlegroups.com>,
 "William D Clinger" <········@yahoo.com> wrote:

> Emilio Lopes wrote:
> > Do you guys know Clinger's explicit renaming macros?
> >
> >    Hygienic macros through explicit renaming
> >    William Clinger
> >    Lisp Pointers IV(4), 25-28, December 1991.
> 
> That's just a tutorial paper, and a pretty old one at that.
> For a more modern and technical presentation, complete
> with implementation and discussion, see
> 
> Andr� van Tonder.  SRFI 72: Simple Hygienic Macros.
> http://srfi.schemers.org/srfi-72/

SRFI-72 is quite a bit more sophisticated than what I've proposed here.  
My proposal is not hygienic, it is merely an alternative hack to the 
Lisp-2 hack.

rg
From: Kaz Kylheku
Subject: Re: An alternative to Lisp-2
Date: 
Message-ID: <1146591097.310514.247170@u72g2000cwu.googlegroups.com>
Ron Garret wrote:
> Lisp-2 is a hacky but workable solution to the problem of unintended
> name capture in macros.  But as

Lisp-2 is neither hacky, nor is it a solution to a name capture. Lisp-2
and Lisp-1 are both just points in the solution space for designing
expression evaluation.

Both approaches require special treatment of the leftmost position of
the compound expression.

Lisp-1 isn't any more clean or pure than Lisp-2. Lisp-1 has to have
hacks in order to support special operators and macros.  An operator is
a function that has to be called differently and at a different time
from a regular function, yet the same syntax is used to codify both.
When a Lisp-1 encounters the syntax (op arg), it has to decide whether
OP is a a special or macro operator, or a function. Thus, the OP cannot
just be blindly evaluated in the same way that ARG is. The compiler or
macro-expander has to look up OP in the environment and decide what to
do. If it is discovered that OP has an ordinary variable binding, then
evaluation is arranged, and the result is expected to be a function
that is called. If OP is a macro, it has to be expanded, or else if it
is a special operator, then the special processing for that operator
has to be invoked.

So if Lisp-2 is hacky, so is Lisp-1. Lisp-1 has to make static
inferences about the run-time values of bindings. It also has
inconsistencies. For instance, this cannot work:

  (defun foo (macro-op)
    (macro-op 42))

When you supply the argument to FOO to be the value of MACRO-OP, it has
to be a function. Why can't it be any operator whatsoever, special or
macro? It's because the code was statically analyzed. At the time the
function was processed, the language implementation (compiler or
interpreter) decided that since MACRO-OP has a variable binding, it
cannot be an operator. An operator must be introduced by a special
binding construct just for operators. Hmm, so much for the idea that
one binding does everything!

> http://www.nhplace.com/kent/Papers/Technical-Issues.html
>
> points out it is an incomplete solution, as free function calls can
> still be shadowed by FLET or LABELS (though this is a minor problem in
> practice).  The above paper suggests `(FUNCALL ',#'FOO ...) as a
> substitute for (FOO ...) in macros as an ironclad guarantee against
> unintentional name capture.

Unfortunately `(funcall ',#'foo) only works portably in interpreted
code. What's happening is that a function object is being inserted into
source code as a literal. But a literal has to be an externalizable
object, meaning that a compiler can stick it into an object file.
Functions are not required to be externalizable objects.

If you are just evaluating this in one image, without compiling
anything to object files, it works fine. Whatever is in the source code
can survive into a translation, because it's all in the same image. If
the translation has to be written out to storage and then read back,
possibly in a different image, all bets are off.

>
> Which got me to thinking...
>
> Suppose this were legal:
>
> (#'FOO ...)
>
> Now we could write macros like:
>
> (defmacro frob (blitz)
>   `(,#'list ',blitz (snozbar)))


But (#'FOO ...) is completely different from `(,#'FOO ...).

The correct way to call a top-level function by name, bypassing any
lexical function bindings of that name, is to do this:

  (flet ((list () (values)))
    (funcall (symbol-function 'list) 1 2 3))

  -> (1 2 3)

Didn't you say you have 20 years of Lisp experience?
From: Russell McManus
Subject: Re: An alternative to Lisp-2
Date: 
Message-ID: <87iroour4d.fsf@cl-user.org>
Ron Garret <·········@flownet.com> writes:

> Lisp-2 is a hacky but workable solution to the problem of unintended 
> name capture in macros.  But as
>
> http://www.nhplace.com/kent/Papers/Technical-Issues.html
>
> points out it is an incomplete solution, as free function calls can 
> still be shadowed by FLET or LABELS (though this is a minor problem in 
> practice).  The above paper suggests `(FUNCALL ',#'FOO ...) as a 
> substitute for (FOO ...) in macros as an ironclad guarantee against 
> unintentional name capture.

I never seem to have this problem because of the package system.  If I
write a macro that calls a function, I make sure that it calls a
function either in the CL package or one named by a symbol in my own
package.  I assume that user code won't rebind such symbols, and all
is well.

But maybe I'm missing something.

-russ
From: Pascal Costanza
Subject: Re: An alternative to Lisp-2
Date: 
Message-ID: <4bpcbtF12himpU1@individual.net>
Ron Garret wrote:

> My question is: would this work?  Are there drawbacks that I have 
> overlooked?

What about this?

(flet ((foo (...) ...))
   (macrolet ((bar (...) `(foo ...)))
     ...))

How can you ensure that 'foo is not captured here?


(Maybe this already works, but you said something about global functions.)

Apart from that this looks like the explicit-renaming proposal by Will 
Clinger. See the appendix to R4RS ("Hygienic Macros Through Explicit 
Renaming").

My fear would be that you would probably have to rename quite a lot of 
identifiers.


Pascal

-- 
3rd European Lisp Workshop
July 3-4 - Nantes, France - co-located with ECOOP 2006
http://lisp-ecoop06.bknr.net/
From: Ron Garret
Subject: Re: An alternative to Lisp-2
Date: 
Message-ID: <rNOSPAMon-852F88.10194202052006@news.gha.chartermi.net>
In article <···············@individual.net>,
 Pascal Costanza <··@p-cos.net> wrote:

> Ron Garret wrote:
> 
> > My question is: would this work?  Are there drawbacks that I have 
> > overlooked?
> 
> What about this?
> 
> (flet ((foo (...) ...))
>    (macrolet ((bar (...) `(foo ...)))
>      ...))
> 
> How can you ensure that 'foo is not captured here?

I'm not sure what you mean.  The typical capture scenario involves a 
free reference in a macro definition being bound by code that invokes 
that macro.  But your example has no macro invocations so it's hard to 
divine your intentions.  Could you elaborate?

> (Maybe this already works, but you said something about global functions.)

That's right.  In the above example, all invocations of bar are 
necessarily within the scope of the binding of foo, so they would all 
use the local foo.  If that's not what you want then 1) why are you 
binding foo and 2) you'd write (macrolet ((bar (...) `(#^foo ...

> Apart from that this looks like the explicit-renaming proposal by Will 
> Clinger. See the appendix to R4RS ("Hygienic Macros Through Explicit 
> Renaming").

It's similar, but my proposal is a lot simpler.  I'm not renaming 
identifiers.  I'm introducing syntax to allow explicit access to a 
second (already existing) environment.  This is not unlike Lisp-2, 
except that instead of a function-value split there is now a 
local/global split.

> My fear would be that you would probably have to rename quite a lot of 
> identifiers.

Yes, which is why IMO explicit renaming is a bad idea.

Note that my proposal is NOT hygienic.  It doesn't actually capture the 
lexical environment of the macro definition.  It makes the simplifying 
assumption that macros are either 1) defined a the top level or 2) 
defined in the same block of code that invokes them (i.e. through 
macrolet).  So for example, you can do the following in Clinger's system 
but not in mine:

(flet ( (foo () ...) )
  (defmacro baz (...) `(... (foo ...) ...)))

where foo is intended to refer to the locally bound foo.  But you can't 
do that in Common Lisp either.  My goal here is not to reinvent hygienic 
macros, but rather to reproduce the functionality of Common Lisp macros 
in a Lisp-1 with no more (and preferably less) conceptual complexity and 
typing than naturally occurs in a Lisp-2.

rg
From: Joerg Hoehle
Subject: Re: An alternative to Lisp-2
Date: 
Message-ID: <uslnq2exn.fsf@users.sourceforge.net>
Ron Garret <·········@flownet.com> writes:
> Suppose this were legal:
> (#'FOO ...)

Actually, I think you meant
  (#.#'FOO ...) instead, as that's what your next macro creates:

> Now we could write macros like:
> (defmacro frob (blitz)
>   `(,#'list ',blitz (snozbar)))

This is nothing new.  Some Common Lisps have supported this for
decades -- or at least the (FUNCALL #.#<function object> ...) form.

> My question is: would this work?
It's implementation dependent. 

> Are there drawbacks that I have overlooked?

There's been an old bug in one of Iterate macros which produced
exactly such code.  It's been there for over 10 years.  Until I tested
it with ECLS which reported unability to inline compiled function
objects (instead of a reference via #'NAME to a compiled function)
during compilation.

The bug required a work around in code walker as follows in Iterate:
: ((functionp fn) `(funcall ,fn ,@args)) ;; Siskind's patch for compiled fns

I looked at the code and saw no reason not to use the named reference,
and voil�, Iterate's testsuite now works fine with ECLS.
The above testcase became superfluous at the same time.

The difference was a single QUOTE in a macro!

This story points at one of the possible drawbacks: by including a
reference to a function object (e.g. code vector) instead of its name
(possibly in a lexical context), you can make it a challenging problem
to be able to create binary (.fasl) files that include that reference.
Will they duplicate the code originating from some other file that
contains the original function?  Is that possible at all (closed-over
environment)?

In some implementations, you won't notice, because they will silently
do lots of things to make it work (at the cost of code duplication,
among others).

> My goal here is not to reinvent hygienic macros, but rather to
> reproduce the functionality of Common Lisp macros in a Lisp-1 with no
> more (and preferably less) conceptual complexity and typing than
> naturally occurs in a Lisp-2.
You lost me here.  I think Schemers can be really hapy with hygiene.

Regards,
	Jorg Hohle
Telekom/T-Systems Technology Center