From: ···········@netscape.net
Subject: Capture of functions in macros
Date: 
Message-ID: <1140283169.467514.278970@g43g2000cwa.googlegroups.com>
Hello!

(defun fun () 7)
(defmacro macro () '(fun))

Now this will evaluate to 10:

(flet ((fun () 10)) (macro))

I thought defining the macro like this instead would be a good idea:

(defmacro macro () `(funcall ,#'fun))

Is this a good solution? If it is, do you have any ideas on how to make
such calls in a prettier way?
I thought maybe you could have !(bla 1 2 3) expand into (funcall ,#'bla
1 2 3) within backquotes, but I'm not sure on how to do this.

Thanks!

From: Pascal Costanza
Subject: Re: Capture of functions in macros
Date: 
Message-ID: <45p7huF7sampU1@individual.net>
···········@netscape.net wrote:
> Hello!
> 
> (defun fun () 7)
> (defmacro macro () '(fun))
> 
> Now this will evaluate to 10:
> 
> (flet ((fun () 10)) (macro))
> 
> I thought defining the macro like this instead would be a good idea:
> 
> (defmacro macro () `(funcall ,#'fun))
> 
> Is this a good solution?

No, not really. Your functions and macros should have more distinctive 
names, then you probably don't need such workarounds to ensure that the 
right function is called from a macro.

If you insist on using cryptic names, put the definitions in their own 
package and only export 'macro but not 'fun from that package, then 
you're also pretty safe.


Pascal

-- 
My website: http://p-cos.net
Closer to MOP & ContextL:
http://common-lisp.net/project/closer/
From: ···········@netscape.net
Subject: Re: Capture of functions in macros
Date: 
Message-ID: <1140291144.802048.134000@o13g2000cwo.googlegroups.com>
Pascal Costanza skrev:

> ···········@netscape.net wrote:
> > Hello!
> >
> > (defun fun () 7)
> > (defmacro macro () '(fun))
> >
> > Now this will evaluate to 10:
> >
> > (flet ((fun () 10)) (macro))
> >
> > I thought defining the macro like this instead would be a good idea:
> >
> > (defmacro macro () `(funcall ,#'fun))
> >
> > Is this a good solution?
>
> No, not really.

Could anything bad happen using this approach, or do you just mean it's
ugly?

>Your functions and macros should have more distinctive
> names, then you probably don't need such workarounds to ensure that the
> right function is called from a macro.
>
> If you insist on using cryptic names, put the definitions in their own
> package and only export 'macro but not 'fun from that package, then
> you're also pretty safe.

That sounds good. Thanks!

> Pascal
>
> --
> My website: http://p-cos.net
> Closer to MOP & ContextL:
> http://common-lisp.net/project/closer/
From: Peter Seibel
Subject: Re: Capture of functions in macros
Date: 
Message-ID: <m2pslk2x8z.fsf@gigamonkeys.com>
···········@netscape.net writes:

> Pascal Costanza skrev:
>
>> ···········@netscape.net wrote:
>> > Hello!
>> >
>> > (defun fun () 7)
>> > (defmacro macro () '(fun))
>> >
>> > Now this will evaluate to 10:
>> >
>> > (flet ((fun () 10)) (macro))
>> >
>> > I thought defining the macro like this instead would be a good idea:
>> >
>> > (defmacro macro () `(funcall ,#'fun))
>> >
>> > Is this a good solution?
>>
>> No, not really.
>
> Could anything bad happen using this approach, or do you just mean it's
> ugly?

Yes. You can't (portable) COMPILE-FILE code that uses this macro
because there's no guarantee that the function object can be
externalized. (See section 3.2.4.1 of the standard.) You could "fix"
that by defining the macro as:

  (defmacro macro () `(funcall 'fun))

But in reality Common Lispers tend not to worry about this lack of
hygine in our macros.

-Peter

-- 
Peter Seibel           * ·····@gigamonkeys.com
Gigamonkeys Consulting * http://www.gigamonkeys.com/
Practical Common Lisp  * http://www.gigamonkeys.com/book/
From: Barry Margolin
Subject: Re: Capture of functions in macros
Date: 
Message-ID: <barmar-809575.21485718022006@comcast.dca.giganews.com>
In article <··············@gigamonkeys.com>,
 Peter Seibel <·····@gigamonkeys.com> wrote:

> ···········@netscape.net writes:
> 
> > Pascal Costanza skrev:
> >
> >> ···········@netscape.net wrote:
> >> > Hello!
> >> >
> >> > (defun fun () 7)
> >> > (defmacro macro () '(fun))
> >> >
> >> > Now this will evaluate to 10:
> >> >
> >> > (flet ((fun () 10)) (macro))
> >> >
> >> > I thought defining the macro like this instead would be a good idea:
> >> >
> >> > (defmacro macro () `(funcall ,#'fun))
> >> >
> >> > Is this a good solution?
> >>
> >> No, not really.
> >
> > Could anything bad happen using this approach, or do you just mean it's
> > ugly?
> 
> Yes. You can't (portable) COMPILE-FILE code that uses this macro
> because there's no guarantee that the function object can be
> externalized. (See section 3.2.4.1 of the standard.) You could "fix"
> that by defining the macro as:
> 
>   (defmacro macro () `(funcall 'fun))
> 
> But in reality Common Lispers tend not to worry about this lack of
> hygine in our macros.

One reason why this tends not to be a problem in practice is the use of 
packages.  In many cases, the macro will expand into a call to a 
function private to its package.  A user of the macro would have to go 
out of their way to shadow this function with FLET.

-- 
Barry Margolin, ······@alum.mit.edu
Arlington, MA
*** PLEASE post questions in newsgroups, not directly to me ***
*** PLEASE don't copy me on replies, I'll read them in the group ***
From: Peter Seibel
Subject: Re: Capture of functions in macros
Date: 
Message-ID: <m21wy082uz.fsf@gigamonkeys.com>
Barry Margolin <······@alum.mit.edu> writes:

> In article <··············@gigamonkeys.com>,
>  Peter Seibel <·····@gigamonkeys.com> wrote:
>
>> ···········@netscape.net writes:
>> 
>> > Pascal Costanza skrev:
>> >
>> >> ···········@netscape.net wrote:
>> >> > Hello!
>> >> >
>> >> > (defun fun () 7)
>> >> > (defmacro macro () '(fun))
>> >> >
>> >> > Now this will evaluate to 10:
>> >> >
>> >> > (flet ((fun () 10)) (macro))
>> >> >
>> >> > I thought defining the macro like this instead would be a good idea:
>> >> >
>> >> > (defmacro macro () `(funcall ,#'fun))
>> >> >
>> >> > Is this a good solution?
>> >>
>> >> No, not really.
>> >
>> > Could anything bad happen using this approach, or do you just mean it's
>> > ugly?
>> 
>> Yes. You can't (portable) COMPILE-FILE code that uses this macro
>> because there's no guarantee that the function object can be
>> externalized. (See section 3.2.4.1 of the standard.) You could "fix"
>> that by defining the macro as:
>> 
>>   (defmacro macro () `(funcall 'fun))
>> 
>> But in reality Common Lispers tend not to worry about this lack of
>> hygine in our macros.
>
> One reason why this tends not to be a problem in practice is the use of 
> packages.  In many cases, the macro will expand into a call to a 
> function private to its package.  A user of the macro would have to go 
> out of their way to shadow this function with FLET.

That and the prohibition against locally binding symbols from the
COMMON-LISP package with FLET, etc.

-Peter

-- 
Peter Seibel           * ·····@gigamonkeys.com
Gigamonkeys Consulting * http://www.gigamonkeys.com/
Practical Common Lisp  * http://www.gigamonkeys.com/book/
From: Christophe Rhodes
Subject: Re: Capture of functions in macros
Date: 
Message-ID: <sqirrbvj9b.fsf@cam.ac.uk>
Peter Seibel <·····@gigamonkeys.com> writes:

> Barry Margolin <······@alum.mit.edu> writes:
>
>> One reason why this tends not to be a problem in practice is the use of 
>> packages.  In many cases, the macro will expand into a call to a 
>> function private to its package.  A user of the macro would have to go 
>> out of their way to shadow this function with FLET.
>
> That and the prohibition against locally binding symbols from the
> COMMON-LISP package with FLET, etc.

There is no such prohibition for symbols which are not defined to be
fbound; one needs to be careful when choosing a private name not to
use something which is exported in another rôle.

Christophe
From: Kaz Kylheku
Subject: Re: Capture of functions in macros
Date: 
Message-ID: <1140482857.692827.271190@g43g2000cwa.googlegroups.com>
···········@netscape.net wrote:
> Hello!
>
> (defun fun () 7)
> (defmacro macro () '(fun))
>
> Now this will evaluate to 10:
>
> (flet ((fun () 10)) (macro))
>
> I thought defining the macro like this instead would be a good idea:
>
> (defmacro macro () `(funcall ,#'fun))
>
> Is this a good solution?

It's not a good solution at all, because what it does is stick a
function-object into the source code of the program as a literal.
Literals must be externalizable objects: a compiler must be able to
take literals and put them into an object file.

The proper solution to this problem of lexical function capture is to
use only standard Lisp functions in macro bodies, and to use packages.

It's okay to call Lisp functions because the ANSI CL standrad says that
programs which redefine them (globally or locally) invoke undefined
behavior.

The remaining functions that you use are in your package:

  (defpackage :your-package)

  (in-package :your-package)

  ;;; so you see, FOO here is really YOUR-PACKAGE::FOO.
  (defun foo () 20)
  (defmacro macro () '(foo))

Now inside my package, I don't have a problem, because I do this:

  (defpackage :my-package (:import-from :your-package macro))

  ;; This FOO is MY-PACKAGE::FOO. We did not import YOUR-PACKAGE::FOO,
  ;; which isn't even an exported symbol from that package.

  (defun foo () 10)

  (macro) --> 20

The macro expands to (YOUR-PACKAGE::FOO).

So transparency is achieved by proper use of namespaces.