From: Software Scavenger
Subject: symbol in macro
Date: 
Message-ID: <a6789134.0208302202.3ffe98e2@posting.google.com>
How should a macro refer to a symbol which is expected to exist when
the macro is expanded?

From: Erik Naggum
Subject: Re: symbol in macro
Date: 
Message-ID: <3239763128549848@naggum.no>
* ··········@mailandnews.com (Software Scavenger)
| How should a macro refer to a symbol which is expected to exist when the
| macro is expanded?

  In what way does it not exist when the macro is defined?

-- 
Erik Naggum, Oslo, Norway

Act from reason, and failure makes you rethink and study harder.
Act from faith, and failure makes you blame someone and push harder.
From: Software Scavenger
Subject: Re: symbol in macro
Date: 
Message-ID: <a6789134.0208310214.7573b6c3@posting.google.com>
Erik Naggum <····@naggum.no> wrote in message news:<················@naggum.no>...

>   In what way does it not exist when the macro is defined?

Whatever package the macro is expanded in, it expects to find a
specific symbol in that package.  It can't simply refer to it
directly, because it doesn't know what package it's in until it's
expanded.
From: Erik Naggum
Subject: Re: symbol in macro
Date: 
Message-ID: <3239778982119441@naggum.no>
* ··········@mailandnews.com (Software Scavenger)
| Whatever package the macro is expanded in, it expects to find a specific
| symbol in that package.  It can't simply refer to it directly, because it
| doesn't know what package it's in until it's expanded.

  This sounds like a conceptual mistake of some kind, but if you really want
  to reference a symbol by name in the current package at the time of the
  expansion, something like this should help you get started.

(defmacro ...
  (let ((symbol (intern (symbol-name 'symbol) *package*)))
    `(... ,symbol ...))

-- 
Erik Naggum, Oslo, Norway

Act from reason, and failure makes you rethink and study harder.
Act from faith, and failure makes you blame someone and push harder.
From: Software Scavenger
Subject: Re: symbol in macro
Date: 
Message-ID: <a6789134.0208310935.23e73e7b@posting.google.com>
Erik Naggum <····@naggum.no> wrote in message news:<················@naggum.no>...

> (defmacro ...
>   (let ((symbol (intern (symbol-name 'symbol) *package*)))
>     `(... ,symbol ...))

Yes, what I'm actually using is `(... ,(intern "MYSYMBOL") ...)
but it seems vaguely wrong to me because intern gives me the vague
impression of being for creating the symbol when it doesn't exist.  In
my case, the name of the symbol is a constant, known to the macro, and
it would be an error for the symbol to not exist at macro expansion
time.  I was vaguely wondering if there was something simpler than
intern, something read-only, which could use the fact that the symbol
name is a constant, even though the package is unknown.
From: Hannah Schroeter
Subject: Re: symbol in macro
Date: 
Message-ID: <akqvjq$rhd$2@c3po.schlund.de>
Hello!

Software Scavenger <··········@mailandnews.com> wrote:
>Erik Naggum <····@naggum.no> wrote in message
>news:<················@naggum.no>...

>> (defmacro ...
>>   (let ((symbol (intern (symbol-name 'symbol) *package*)))
>>     `(... ,symbol ...))

>Yes, what I'm actually using is `(... ,(intern "MYSYMBOL") ...)
>but it seems vaguely wrong to me because intern gives me the vague
>impression of being for creating the symbol when it doesn't exist.  In
>my case, the name of the symbol is a constant, known to the macro, and
>it would be an error for the symbol to not exist at macro expansion
>time.  I was vaguely wondering if there was something simpler than
>intern, something read-only, which could use the fact that the symbol
>name is a constant, even though the package is unknown.

#'find-symbol?

Kind regards,

Hannah.
From: Erik Naggum
Subject: Re: symbol in macro
Date: 
Message-ID: <3239805074868605@naggum.no>
* Software Scavenger
| but it seems vaguely wrong to me because intern gives me the vague
| impression of being for creating the symbol when it doesn't exist.

  This is just plain wrong.  The purpose of `intern� is to return the symbol
  with the name you specify.  If the symbol does not exist, is it created.  If
  you really want an existing symbol, use `find-symbol�, instead.

| In my case, the name of the symbol is a constant, known to the macro, and it
| would be an error for the symbol to not exist at macro expansion time.  I
| was vaguely wondering if there was something simpler than intern, something
| read-only, which could use the fact that the symbol name is a constant, even
| though the package is unknown.

  The HyperSpec has a pointer to `find-symbol� in the entry for `intern� in
  the See Also section.  Why do you not use the references when they are so
  readily available to you?

-- 
Erik Naggum, Oslo, Norway

Act from reason, and failure makes you rethink and study harder.
Act from faith, and failure makes you blame someone and push harder.
From: Joe Marshall
Subject: Re: symbol in macro
Date: 
Message-ID: <we6c9.307418$UU1.54428@sccrnsc03>
"Software Scavenger" <··········@mailandnews.com> wrote in message
·································@posting.google.com...
> Erik Naggum <····@naggum.no> wrote in message news:<················@naggum.no>...
>
> >   In what way does it not exist when the macro is defined?
>
> Whatever package the macro is expanded in, it expects to find a
> specific symbol in that package.

Macros are not expanded in a package.
From: Software Scavenger
Subject: Re: symbol in macro
Date: 
Message-ID: <a6789134.0208311837.3e0c129d@posting.google.com>
"Joe Marshall" <·············@attbi.com> wrote in message news:<······················@sccrnsc03>...

> Macros are not expanded in a package.

I mean the current package at the time the reader reads the macro
call.

I'm not looking for a solution at this point, as intern and
find-symbol are fine.  I'm really just wondering whether this is
considered a significant issue and whether there are other well known
ways to handle it.

Normally when a symbol is mentioned in a macro its package will be in
the context of the macro definition rather than of the macro call. 
But it seems obvious to me that the context of the macro call is what
might be wanted and/or assumed by a programmer writing a macro without
taking such issues into account.  But, maybe, by a coincidence of the
ways things are normally done, this issue hardly ever manifests
itself, so it doesn't get noticed.
From: Erik Naggum
Subject: Re: symbol in macro
Date: 
Message-ID: <3239909790495015@naggum.no>
* ··········@mailandnews.com (Software Scavenger)
| Normally when a symbol is mentioned in a macro its package will be in the
| context of the macro definition rather than of the macro call.  But it seems
| obvious to me that the context of the macro call is what might be wanted
| and/or assumed by a programmer writing a macro without taking such issues
| into account.  But, maybe, by a coincidence of the ways things are normally
| done, this issue hardly ever manifests itself, so it doesn't get noticed.

  Why is it referring to that symbol in the first place?  Do you want a macro
  to rely on a protocol of use that requires certain symbols to be defined
  somehow in the package defined by the programmer that uses your macro and
  you do not want to supply a default definition?  I think I understand what
  you want to do, but really I do not understand why you want to do it or
  under what circumstances it would be the right thing to do.

-- 
Erik Naggum, Oslo, Norway

Act from reason, and failure makes you rethink and study harder.
Act from faith, and failure makes you blame someone and push harder.
From: Software Scavenger
Subject: Re: symbol in macro
Date: 
Message-ID: <a6789134.0209012155.573fd561@posting.google.com>
Erik Naggum <····@naggum.no> wrote in message news:<················@naggum.no>...

>   Why is it referring to that symbol in the first place?  Do you want a macro
>   to rely on a protocol of use that requires certain symbols to be defined
>   somehow in the package defined by the programmer that uses your macro and
>   you do not want to supply a default definition?  I think I understand what
>   you want to do, but really I do not understand why you want to do it or
>   under what circumstances it would be the right thing to do.

I don't actually have a specific problem I'm trying to solve.  I tend
to do a lot of experimenting with hairy macros.  It's mostly temporary
throwaway experimental code.  E.g. writing my own versions of DEFUN
etc. just to experiment with them and think about why certain ways of
doing things are better, etc.  I happened to notice this issue while
doing that kind of stuff, and started wondering whether it affected
other situations, etc.  What I really wanted from this discussion was
some idea of how much other CL programmers encounter this issue and
how they usually handle it.  Mostly just curiosity about it, because
when I first encountered it, it seemed like a mildly strange and
noteworthy issue to me.
From: Kaz Kylheku
Subject: Re: symbol in macro
Date: 
Message-ID: <akr3uo$cc1$2@luna.vcn.bc.ca>
In article <····························@posting.google.com>, Software
Scavenger wrote:
> Erik Naggum <····@naggum.no> wrote in message news:<················@naggum.no>...
> 
>>   In what way does it not exist when the macro is defined?
> 
> Whatever package the macro is expanded in, it expects to find a
> specific symbol in that package.  It can't simply refer to it
> directly, because it doesn't know what package it's in until it's
> expanded.

In that case, the symbol should probably appear as a parameter to the macro.

(defmacro mac (mystery-symbol)
  ;; insert mystery-symbol into template
  `(foo ... ,mystery-symbol ...))
From: Software Scavenger
Subject: Re: symbol in macro
Date: 
Message-ID: <a6789134.0208311848.343e8a6@posting.google.com>
Kaz Kylheku <···@ashi.footprints.net> wrote in message news:<············@luna.vcn.bc.ca>...

> In that case, the symbol should probably appear as a parameter to the macro.

Yes, in most cases it would, and that would solve the problem. 
However there are some cases where the name of the symbol is constant,
as part of the paradigm of the macro, and it would be silly to repeat
it with every call to that macro.
From: Tim Bradshaw
Subject: Re: symbol in macro
Date: 
Message-ID: <ey3fzwtrbjg.fsf@cley.com>
* Software Scavenger wrote:
> Yes, in most cases it would, and that would solve the problem. 
> However there are some cases where the name of the symbol is constant,
> as part of the paradigm of the macro, and it would be silly to repeat
> it with every call to that macro.

I think you need to give an example.  It sounds to me like what you
are trying to do is an example of the kind of thing that, say, my
COLLECTING macro does: namely introduce a (fixed) name in the scope of
the macro, rather providing some meaning for a user-given name as a
classic WITH-x macro does:

So the canonical WITh-x looks like:

    (with-frobnicated-widget (foo ...)
      ... use FOO which has some meaning in this scope ...)

concrete example:

    (with-open-file (in ...)
      ... IN is bound to a stream here ...)

But the other (rarer) kind of macro does something like this:

    (collecting
      ... in this scope (COLLECT x) has meaning ...)

Here you didn't need to name the magic thing that was bound, it was
assumed.

And the answer is easy.  When you define the macro, you *also* define
the symbol(s) that it introduces, and simply export them too.  So in a
package where COLLECTING is used, COLLECT is also available.  Since
COLLECT has no global information associated with it, this doesn't
introduce any significant problems.

--tim
    
From: Software Scavenger
Subject: Re: symbol in macro
Date: 
Message-ID: <a6789134.0209011542.68a36e56@posting.google.com>
Tim Bradshaw <···@cley.com> wrote in message news:<···············@cley.com>...

> And the answer is easy.  When you define the macro, you *also* define
> the symbol(s) that it introduces, and simply export them too.  So in a
> package where COLLECTING is used, COLLECT is also available.  Since
> COLLECT has no global information associated with it, this doesn't
> introduce any significant problems.

So you export COLLECT for the sole purpose of making sure the macro
expansion refers to the same COLLECT as the macro definition?  Is that
a better solution than using `(... ,(intern "COLLECT") ...) ?
From: Thomas F. Burdick
Subject: Re: symbol in macro
Date: 
Message-ID: <xcv7ki4j4v8.fsf@hurricane.OCF.Berkeley.EDU>
··········@mailandnews.com (Software Scavenger) writes:

> Tim Bradshaw <···@cley.com> wrote in message news:<···············@cley.com>...
> 
> > And the answer is easy.  When you define the macro, you *also* define
> > the symbol(s) that it introduces, and simply export them too.  So in a
> > package where COLLECTING is used, COLLECT is also available.  Since
> > COLLECT has no global information associated with it, this doesn't
> > introduce any significant problems.
> 
> So you export COLLECT for the sole purpose of making sure the macro
> expansion refers to the same COLLECT as the macro definition?  Is that
> a better solution than using `(... ,(intern "COLLECT") ...) ?

Yes; it's better because it's less surprising.  All the names of
things associated with the COLLECTING macro live in its package.
Using the COLLECTING macro doesn't magically create new symbols in
your consuming package.  Now, if I USE-PACKAGE COLLECTING's package,
it doesn't make much of a difference.  But for code like this:

  (in-package "FOO")
  (defun foo (...)
    (utils:collecting
       ...))

I obviously don't want the external symbols from the UTILS package
imported into FOO -- and it would be really annoying, given code like
this, for UTILS:COLLECTING to decide to effectively do this anyway.

Really, this is important for preserving the (Common)Lispiness of the
language.  If you unconditionally go ahead and make the COLLECT symbol
in my FOO package, you're not using the symbol COLLECT as a symbol,
but as a string specifier.

-- 
           /|_     .-----------------------.                        
         ,'  .\  / | No to Imperialist war |                        
     ,--'    _,'   | Wage class war!       |                        
    /       /      `-----------------------'                        
   (   -.  |                               
   |     ) |                               
  (`-.  '--.)                              
   `. )----'                               
From: Software Scavenger
Subject: Re: symbol in macro
Date: 
Message-ID: <a6789134.0209020954.258c3324@posting.google.com>
···@hurricane.OCF.Berkeley.EDU (Thomas F. Burdick) wrote in message news:<···············@hurricane.OCF.Berkeley.EDU>...

>   (in-package "FOO")
>   (defun foo (...)
>     (utils:collecting
>        ...))

I see your point.  The user of the macro in this case would use
utils:collect with utils:collecting, and could also use foo:collect
for other purposes.

Another advantage of exporting the symbol, in some cases, would be
that you could give it a default which could cause some kind of
quasi-coherent error message if the macro expected the user to bind it
but the user neglected to.  (As opposed to the seemingly incoherent
error messages given in a lot of macro usage situations.)
From: Paul F. Dietz
Subject: Re: symbol in macro
Date: 
Message-ID: <3D72B0C3.A42328F3@dls.net>
Software Scavenger wrote:

> So you export COLLECT for the sole purpose of making sure the macro
> expansion refers to the same COLLECT as the macro definition?  Is that
> a better solution than using `(... ,(intern "COLLECT") ...) ?

It would enable you to detect the conflict if two macros want to
use a COLLECT sub(?)macro.  You can then use appropriate package fu
to get around the problem.

	Paul
From: Paul F. Dietz
Subject: Re: symbol in macro
Date: 
Message-ID: <3D72B230.316527CA@dls.net>
Software Scavenger wrote:

> So you export COLLECT for the sole purpose of making sure the macro
> expansion refers to the same COLLECT as the macro definition?  Is that
> a better solution than using `(... ,(intern "COLLECT") ...) ?

Oh, and calling INTERN without specifying the package argument
is usually asking for trouble.  In this case, how do you know
the value of that variable is the same as when you read the
form being macro expanded?

	Paul
From: Erik Naggum
Subject: Re: symbol in macro
Date: 
Message-ID: <3239925474372819@naggum.no>
* ··········@mailandnews.com (Software Scavenger)
| So you export COLLECT for the sole purpose of making sure the macro
| expansion refers to the same COLLECT as the macro definition?  Is that
| a better solution than using `(... ,(intern "COLLECT") ...) ?

  I think I see your point, but let me rephrase it.  Is it the better solution
  to let macros define other local macros and functions with `macrolet�, `flet�,
  and `labels� with symbols in the package in which the macro is defined or in
  the current package at the time of expansion?  This is a good question.

  Common Lisp has clearly made the decision that it is the better solution to
  this problem to rely on the reader for the package of the symbols than to
  attempt to control the package at macro-expansion time.  There are probably
  many reasons for this, but the ones I can think of include the fact that the
  creation of symbols has traditionally been a layered concept and has been
  taken care of by the reader quite independently from any where the symbols
  would be used in the system and the rather obvious conclusion from the
  amount of work involved in circumventing this mechanism in order to make a
  macro more package-friendly, if that is what this is about.

  However, what would it take to write macros with a conservative view to
  packages?  Let me test this on an alternative to if just for show

(defmacro if (condition then-clause &optional else-clause)
  `(cl:if ,condition
       ,(cl:if (and (listp then-clause)
                    (eq (car then-clause) (intern (symbol-name 'then))))
            `(progn ,(cdr then-clause))
          then-clause)
     ,(cl:if (and (listp else-clause)
                  (eq (car else-clause) (intern (symbol-name 'else))))
          `(progn ,(cdr else-clause))
        else-clause)))

  This is not terribly different from or more difficult than using just the
  symbols, but it needs to be done manually, or some additional macrology
  needs to be defined that sort of re-interns the symbol.  Perhaps this is
  what it should be called?

(defun re-intern (symbol)
  "Re-intern the symbol in the current package."
  (intern (symbol-name symbol) *package*))

  Now we can write

(defmacro if (condition then-clause &optional else-clause)
  `(cl:if ,condition
       ,(cl:if (and (listp then-clause)
                    (eq (car then-clause) (re-intern 'then)))
            `(progn ,(cdr then-clause))
          then)
     ,(cl:if (and (listp else-clause)
                  (eq (car else-clause) (re-intern 'else)))
          `(progn ,(cdr else-clause))
        else)))

  which is a little bit less intrusive.  I considered a macro with-reinterned
  but that left the symbols unquoted in the body and that just looked wrong.

  Suppose we want to write this with `macrolet�, instead, although we now make
  it possible to use then `then� and `else� too many places in the code.  It
  could look like this:

(defmacro if (condition then-clause &optional else-clause)
  `(cl:if ,condition
       (macrolet ((,(re-intern 'then) (&body forms) `(progn ,@forms)))
         ,then-clause)
     (macrolet ((,(re-intern 'else) (&body forms) `(progn ,@forms)))
        ,else-clause)))

  If it is felt to be exceptionall important to be able to do this, one might
  imagine reader-macro support for it, as well:

(defmacro if (condition then-clause &optional else-clause)
  `(cl:if ,condition
       (macrolet ((#`then (&body forms) `(progn ,@forms)))
         ,then-clause)
     (macrolet ((#`else (&body forms) `(progn ,@forms)))
        ,else-clause)))

  Is something like this in the vicinity of what you had in mind?

-- 
Erik Naggum, Oslo, Norway

Act from reason, and failure makes you rethink and study harder.
Act from faith, and failure makes you blame someone and push harder.
From: Software Scavenger
Subject: Re: symbol in macro
Date: 
Message-ID: <a6789134.0209021000.9ef822f@posting.google.com>
Erik Naggum <····@naggum.no> wrote in message news:<················@naggum.no>...

>   Is something like this in the vicinity of what you had in mind?

Actually, having followed the discussion this far (keeping in mind
that my news server lags by several hours) I'm now leaning towards the
"export" solution.  It didn't seem very elegant at first, because it
seemed to clutter the list of exported names.  But after following the
discussion and thinking about it some more, it seems a lot more
elegant now, and the clutter isn't really much of a factor, because
the number  of symbols affected by this issue is small.
From: Tim Bradshaw
Subject: Re: symbol in macro
Date: 
Message-ID: <ey3ptvwodn2.fsf@cley.com>
* Software Scavenger wrote:

> So you export COLLECT for the sole purpose of making sure the macro
> expansion refers to the same COLLECT as the macro definition?  Is that
> a better solution than using `(... ,(intern "COLLECT") ...) ?

yes, I think so.  It's the same trick as, say CALL-NEXT-METHOD, but
even lighter weight.

The downsides:

COLLECT belongs to the ORG.TFEB.HAX package, so any other package
which wants to export a symbol with that name needs to be careful if
it also wants to use ORG.TFEB.HAX.  But not very careful, in fact - if
you export a symbol whose name is the same as an external symbol from
a package that you use then you also magically import that external
symbol (at least, you do if you use defpackage).

Collecting won't coexist with a package which exports some other
symbol called COLLECT, and this will be detected at package definition
time.  I *suppose* this is a downside - I'd personally be pretty
unhappy if COLLECT sometimes meant one thing and sometimes another.

Things that aren't downsides but that people might think are:

COLLECT has no global meanings associated with it: users are
perfectly free to use it for any purposes they want.  This is unlike
CALL-NEXT-METHOD, say.  Only programs that are doing fairly
sophisticated package-system introspection will ever notice that it
comes from another package.

The upsides:

I have one COLLECT symbol instead a number equal to the number of
packages that use ORG.TFEB.HAX:COLLECTING.

Note that in the same vein, I hate the LOOP macro's trick of using
names instead of symbols, resulting in hundreds of spurious interned
symbols.  If I had a complete list of standard loop keywords in easily
usable form, I'd define a LOOP-KEYWORDS package and have all my
packages use that.

Ultimately, I guess it's a style thing.

--tim
From: Hannah Schroeter
Subject: Re: symbol in macro
Date: 
Message-ID: <akvu22$vqp$1@c3po.schlund.de>
Hello!

Tim Bradshaw  <···@cley.com> wrote:
>[...]

>Note that in the same vein, I hate the LOOP macro's trick of using
>names instead of symbols, resulting in hundreds of spurious interned
>symbols.  If I had a complete list of standard loop keywords in easily
>usable form, I'd define a LOOP-KEYWORDS package and have all my
>packages use that.

I've begun to accustom myself to use keywords for that. I.e.

(loop :for i :from 1 :to 10
      :do (foo))

Kind regards,

Hannah.
From: Coby Beck
Subject: Re: symbol in macro
Date: 
Message-ID: <akrsga$21sl$1@otis.netspace.net.au>
"Kaz Kylheku" <···@ashi.footprints.net> wrote in message
·················@luna.vcn.bc.ca...
> In article <····························@posting.google.com>, Software
> Scavenger wrote:
> > Erik Naggum <····@naggum.no> wrote in message
news:<················@naggum.no>...
> >
> >>   In what way does it not exist when the macro is defined?
> >
> > Whatever package the macro is expanded in, it expects to find a
> > specific symbol in that package.  It can't simply refer to it
> > directly, because it doesn't know what package it's in until it's
> > expanded.
>
> In that case, the symbol should probably appear as a parameter to the
macro.
>

That was my first thought as well.

--
Coby Beck
(remove #\Space "coby 101 @ bigpond . com")
From: Kaz Kylheku
Subject: Re: symbol in macro
Date: 
Message-ID: <akr3un$cc1$1@luna.vcn.bc.ca>
In article <····························@posting.google.com>, Software
Scavenger wrote:
> How should a macro refer to a symbol which is expected to exist when
> the macro is expanded?

You mean ``to a variable or function *binding* that will exist in the
environment of the expansion,'' surely?

You can't utter a symbol name without causing that symbol to exist right away;
that is taken care of by interning.