From: Pillsy
Subject: Why no SYMBOL-MACRO-FUNCTION?
Date: 
Message-ID: <1185890682.686818.143580@l70g2000hse.googlegroups.com>
It's not so hard to find the expansion function associated with an
ordinary macro---you just use MACRO-FUNCTION. Finding information
about the function or value associated with a symbol is similarly
straightforward. There doesn't seem to be as good a way for doing the
same with a symbol: AFAIK the best you can do is check the second
return value of macroexpand.

There's also no good way to get rid of a symbol-macro definition for a
symbol; FMAKUNBOUND works for regular macros, but for some reason
MAKUNBOUND doesn't work for symbol macros,

These have all been things I've wanted to do on occasion (for
debugging purposes), and it seems a little strange that I can't.

Cheers,
Pillsy

From: Kaz Kylheku
Subject: Re: Why no SYMBOL-MACRO-FUNCTION?
Date: 
Message-ID: <1185900344.732534.163520@b79g2000hse.googlegroups.com>
On Jul 31, 7:04 am, Pillsy <·········@gmail.com> wrote:
> It's not so hard to find the expansion function associated with an
> ordinary macro---you just use MACRO-FUNCTION. Finding information
> about the function or value associated with a symbol is similarly
> straightforward. There doesn't seem to be as good a way for doing the
> same with a symbol: AFAIK the best you can do is check the second
> return value of macroexpand.

Interestingly, HyperSpec clearly talks about symbol macros having a
function. Obviously, it's just a trivial function that returns the
specified expansion, so it's not particularly interesting. If there
were a SYMBOL-MACRO-FUNCTION, it wouldn't be that useful unless it was
assignable.

The functionality of a custom function behind a symbol macro can be
obtained by expanding the symbol to compound form that calls an
ordinary macro.

> There's also no good way to get rid of a symbol-macro definition for a
> symbol; FMAKUNBOUND works for regular macros, but for some reason
> MAKUNBOUND doesn't work for symbol macros,

I would regard that as an implementation bug, since the symbol macro
is a kind of binding, and the requirement for MAKUNBOUND is to just
remove the symbol's binding. There is no clause there to exclude
symbol macros. Just my interpretation.
From: Kalle Olavi Niemitalo
Subject: Re: Why no SYMBOL-MACRO-FUNCTION?
Date: 
Message-ID: <87sl7398nd.fsf@Astalo.kon.iki.fi>
Kaz Kylheku <········@gmail.com> writes:

> I would regard that as an implementation bug, since the symbol macro
> is a kind of binding, and the requirement for MAKUNBOUND is to just
> remove the symbol's binding.

I disagree.  SYMBOL-MACROLET and DEFINE-SYMBOL-MACRO define
symbol macros in a lexical environment (see 3.1.1.3), and
MAKUNBOUND affects bindings in a dynamic or global environment.
(let ((var t)) (makunbound 'var) var) evaluates to T; why should
it be different with a symbol macro.

Would you expect BOUNDP, SYMBOL-VALUE, SETF SYMBOL-VALUE, and
PROGV to expand the symbol macro, too?
From: Kent M Pitman
Subject: Re: Why no SYMBOL-MACRO-FUNCTION?
Date: 
Message-ID: <uir7zhk4u.fsf@nhplace.com>
Kalle Olavi Niemitalo <···@iki.fi> writes:

> Kaz Kylheku <········@gmail.com> writes:
> 
> > I would regard that as an implementation bug, since the symbol macro
> > is a kind of binding, and the requirement for MAKUNBOUND is to just
> > remove the symbol's binding.
> 
> I disagree.  SYMBOL-MACROLET and DEFINE-SYMBOL-MACRO define
> symbol macros in a lexical environment (see 3.1.1.3), and
> MAKUNBOUND affects bindings in a dynamic or global environment.
> (let ((var t)) (makunbound 'var) var) evaluates to T; why should
> it be different with a symbol macro.
> 
> Would you expect BOUNDP, SYMBOL-VALUE, SETF SYMBOL-VALUE, and
> PROGV to expand the symbol macro, too?

Well, while I agree with your conclusion, I don't agree with the stated
rationale. :)

I think the reason MAKUNBOUND shouldn't affect the symbol macro is that
it is not defined to do so.  Appeals to other operators are useful in
inspecting the goodness of the design, but don't contribute to the question
of whether an implementation has made an error, IMO.

Certainly if one wanted to talk about whether the designers made an
error in spec'ing this out, that'd be fair game. FMAKUNBOUND removes
macro definitions, for example.  (By analogy, in design space, not in
spec interpretation space, one might expect that at least the global
symbol macro would become undefined.  But, back in spec interpretation
space, the spec doesn't say so, and that's that.)  Also,
SYMBOL-FUNCTION's relationship to macros is murky, indicating that
even on that point, the committee was unsure.  So there would be
arguments on both sides.  But I think the designers felt special
variables had a lot of history and while they wanted to add symbol
macros, they didn't want to mess up specials in thep process, so while
I don't recall a specific discussion, I have some reason to believe it
was quasi-intentional that MAKUNBOUND wasn't made to do this service.

Personally, I don't necessarily think the definition is wrong, and
particularly because I'm unclear on whether global lexical variables
(which might be implemented by symbol macros) should be possible to
MAKUNBOUND... I'm not so sure they should be.  (That doesn't mean I'm
right, of course; I'm just one opinion of probably many.)  I'm
inclined to believe that symbol macros and special variables should
quite reasonably be kept separate.
From: Harald Hanche-Olsen
Subject: Re: Why no SYMBOL-MACRO-FUNCTION?
Date: 
Message-ID: <pcok5sfbtu8.fsf@shuttle.math.ntnu.no>
+ Kalle Olavi Niemitalo <···@iki.fi>:

| I disagree.  SYMBOL-MACROLET and DEFINE-SYMBOL-MACRO define
| symbol macros in a lexical environment (see 3.1.1.3),

They do?  Then I must confess that either I do not understand what
this sentence from the specification of DEFINE-SYMBOL-MACRO means, or
I don't understand the concept of lexical environment.

  Globally establishes an expansion function for the symbol macro
  named by symbol.

| (let ((var t)) (makunbound 'var) var) evaluates to T; why should
| it be different with a symbol macro.

What makes you think it's different with a symbol macro? The local
binding for VAR should shadow any symbol macro definition of it.
Just in case I misunderstand what you're saying, this is what I mean:

cl-user> (define-symbol-macro /foo/ (list 42))
/foo/
cl-user> (let ((/foo/ t)) (makunbound '/foo/) /foo/)
t

-- 
* Harald Hanche-Olsen     <URL:http://www.math.ntnu.no/~hanche/>
- It is undesirable to believe a proposition
  when there is no ground whatsoever for supposing it is true.
  -- Bertrand Russell
From: Kent M Pitman
Subject: Re: Why no SYMBOL-MACRO-FUNCTION?
Date: 
Message-ID: <uzm1avroq.fsf@nhplace.com>
Harald Hanche-Olsen <······@math.ntnu.no> writes:

> + Kalle Olavi Niemitalo <···@iki.fi>:
> 
> | I disagree.  SYMBOL-MACROLET and DEFINE-SYMBOL-MACRO define
> | symbol macros in a lexical environment (see 3.1.1.3),
> 
> They do?  Then I must confess that either I do not understand what
> this sentence from the specification of DEFINE-SYMBOL-MACRO means, or
> I don't understand the concept of lexical environment.

Well, one can say the effect of DEFINE-SYMBOL-MACRO is something that
is effectively lexical in the sense that neither SYMBOL-MACROLET nor
any kind of dynamic binding interferes with it, so a lexically apparent
reference means what it appears to mean.

Likewise, SYMBOL-MACROLET has contained effect that does not extend
beyond the lexically enclosed text.

I think to some extent the remark was intended to say that in the
case of

 (defvar *something* 'fooey)
 (symbol-macrolet ((foo *something*))
   (makunbound 'foo)
   foo)

you can't get rid of the binding of FOO because FOO is lexically bound,
not dynamically bound.

>   Globally establishes an expansion function for the symbol macro
>   named by symbol.
> 
> | (let ((var t)) (makunbound 'var) var) evaluates to T; why should
> | it be different with a symbol macro.
> 
> What makes you think it's different with a symbol macro?

Because having done:

(defvar *foo* 3)

(define-symbol-macro foo *foo*)

you can't do

(let ((foo 17)) (symbol-value 'foo))

and find 3.  So, if you believed these arguments were settled by issues
of consistency rather than by looking at the spec and seeing what the
definition was, why would should (makunbound 'foo) undo what 
(symbol-value 'foo) cannot access?

> The local
> binding for VAR should shadow any symbol macro definition of it.
> Just in case I misunderstand what you're saying, this is what I mean:
> 
> cl-user> (define-symbol-macro /foo/ (list 42))
> /foo/
> cl-user> (let ((/foo/ t)) (makunbound '/foo/) /foo/)
> t

I'm not sure why this is relevant.
From: Harald Hanche-Olsen
Subject: Re: Why no SYMBOL-MACRO-FUNCTION?
Date: 
Message-ID: <pco8x8ugkd7.fsf@shuttle.math.ntnu.no>
+ Kent M Pitman <······@nhplace.com>:

| Harald Hanche-Olsen <······@math.ntnu.no> writes:
|
|> + Kalle Olavi Niemitalo <···@iki.fi>:
|> 
|> | I disagree.  SYMBOL-MACROLET and DEFINE-SYMBOL-MACRO define
|> | symbol macros in a lexical environment (see 3.1.1.3),
|> 
|> They do?  Then I must confess that either I do not understand what
|> this sentence from the specification of DEFINE-SYMBOL-MACRO means, or
|> I don't understand the concept of lexical environment.
|
| Well, one can say the effect of DEFINE-SYMBOL-MACRO is something
| that is effectively lexical in the sense that neither
| SYMBOL-MACROLET nor any kind of dynamic binding interferes with it,
| so a lexically apparent reference means what it appears to mean.

Okay, that was an interpretation I hadn't thought of.
(I should have made clear that I had no similar objection regarding
DEFINE-SYMBOL-MACRO of course.)

Now we're getting into the part where the two of us have seem to have
read the OP very differently:

|> | (let ((var t)) (makunbound 'var) var) evaluates to T; why should
|> | it be different with a symbol macro.
|> 
|> What makes you think it's different with a symbol macro?
|
| Because having done:
|
| (defvar *foo* 3)
|
| (define-symbol-macro foo *foo*)
|
| you can't do
|
| (let ((foo 17)) (symbol-value 'foo))
|
| and find 3.

And neither can you do (symbol-value 'foo) on its own, since it does
not access foo as a variable, and hence its symbol-macro definition
does not come into play.

| So, if you believed these arguments were settled by issues of
| consistency rather than by looking at the spec and seeing what the
| definition was, why would should (makunbound 'foo) undo what
| (symbol-value 'foo) cannot access?

Is that a rhetorical question?

|> The local
|> binding for VAR should shadow any symbol macro definition of it.
|> Just in case I misunderstand what you're saying, this is what I mean:
|> 
|> cl-user> (define-symbol-macro /foo/ (list 42))
|> /foo/
|> cl-user> (let ((/foo/ t)) (makunbound '/foo/) /foo/)
|> t
|
| I'm not sure why this is relevant.

It's relevant only in the sense that I had interpreted Kalle's remark
as saying the above should not return t.  But maybe it only
demonstrates my lack of skill in reading between the lines.

I am getting confused.  Not, I believe, about how symbol macros work,
but about what exactly the disagreement is, or indeed whether there
even is disagreement in the first place.

-- 
* Harald Hanche-Olsen     <URL:http://www.math.ntnu.no/~hanche/>
- It is undesirable to believe a proposition
  when there is no ground whatsoever for supposing it is true.
  -- Bertrand Russell
From: Kent M Pitman
Subject: Re: Why no SYMBOL-MACRO-FUNCTION?
Date: 
Message-ID: <uzm1ajb6d.fsf@nhplace.com>
Harald Hanche-Olsen <······@math.ntnu.no> writes:

> ...
> | Well, one can say the effect of DEFINE-SYMBOL-MACRO is something
> | that is effectively lexical in the sense that neither
> | SYMBOL-MACROLET nor any kind of dynamic binding interferes with it,
> | so a lexically apparent reference means what it appears to mean.
> 
> Okay, that was an interpretation I hadn't thought of.

I had a suspicion it was that, since I didn't really disagree with
your post.

> ... I am getting confused.  Not, I believe, about how symbol macros work,
> but about what exactly the disagreement is, or indeed whether there
> even is disagreement in the first place.

Heh.  I'm not sure I know either at this point.  I think there was
some claim that something was broken, which I think it pretty clearly
isn't since it works as specified.  Beyond that, there's the issue of
whether the spec is "obviously wrong", and I think it's pretty clear
that while you can make a case that it's "wrong" (by merely
disagreeing), it's harder to make a case that it's "obviously wrong"
(which in my mind implies showing that the "right" behavior one is
lobbying for is not just "a reasoned choice among one of several
possibly-right behaviors" but in fact "a uniquely/canonically right
behavior").
From: Kalle Olavi Niemitalo
Subject: Re: Why no SYMBOL-MACRO-FUNCTION?
Date: 
Message-ID: <876440a106.fsf@Astalo.kon.iki.fi>
Pillsy <·········@gmail.com> writes:

> It's not so hard to find the expansion function associated with an
> ordinary macro---you just use MACRO-FUNCTION. Finding information
> about the function or value associated with a symbol is similarly
> straightforward. There doesn't seem to be as good a way for doing the
> same with a symbol: AFAIK the best you can do is check the second
> return value of macroexpand.

(defun symbol-macro-function (symbol environment)
  (let* ((functions '())
         (old-hook *macroexpand-hook*)
         (*macroexpand-hook*
         #'(lambda (function hooked-sym hooked-env)
             ;; There is no standard way to compare environments.
             (when (eq hooked-sym symbol)
               (pushnew function functions))
             (funcall old-hook function hooked-sym hooked-env))))
    (when (nth-value 1 (macroexpand-1 symbol environment))
      (assert (= (length functions) 1) (functions)
              "The symbol macro ~S seems to have ~R macro functions."
              symbol (length functions))
      (first functions))))

However, an implementation may use the same macro function for
all symbol macros.

MACROEXPAND-1 of SBCL 0.9.5.50 does not call *MACROEXPAND-HOOK*
when expanding a symbol macro, even though the spec clearly
requires that.  I don't have a newer version available for
testing, but from the source it appears this has not been fixed.

http://sbcl.cvs.sourceforge.net/sbcl/sbcl/src/code/macroexpand.lisp?view=markup