From: Pascal Costanza
Subject: Why no compiler-macrolet?
Date: 
Message-ID: <41ptbfF1f4kcsU1@individual.net>
Hi,

There is not only no compiler-macrolet in ANSI Common Lisp that could be 
used to define local compiler macros, Section 3.2.2.1.2 of the HyperSpec 
even "forcefully" states that "compiler macro definitions are strictly 
global."

Is there a reason why this is the case? (It sounds as if there were a 
profound reason, but I cannot come up with a good rationale myself.)

Local compiler macros would, for example, be useful for introducing 
local functions with possible optimizations in (regular) macros. 
Consider the introduction of call-next-method in a defmethod form. It 
could be roughly introduced like this:

(flet ((call-next-method (&rest args)
          ... a regular function definition ...))
   (compiler-macrolet
       ((call-next-method (&rest args)
          ... an optimized version for 80% of all cases ...))
     ... method body))

What's the point in not allowing this?


Thanks for any hints,
Pascal

-- 
My website: http://p-cos.net
Closer to MOP & ContextL:
http://common-lisp.net/project/closer/

From: Joerg Hoehle
Subject: Re: Why no compiler-macrolet?
Date: 
Message-ID: <uoe2rkpht.fsf@users.sourceforge.net>
Pascal Costanza <··@p-cos.net> writes:
[no compiler-macrolet in ANSI CL]
I presume it's due to the impossibility to portably assume that
   (compiler-macrolet
     code-that-shall-be-affected-by-it
indeed will be processed at the time you presuppose it will.

There's a simple (naive) "interpretation" model of how compilation
works, where such a constructs would make sense (i.e. recursively walk
the source code).  But that's not the only model or implementation.  I
believe that's why such a construct could not be kept in ANSI-CL.

Regards,
	Jorg Hohle
Telekom/T-Systems Technology Center
From: Pascal Costanza
Subject: Re: Why no compiler-macrolet?
Date: 
Message-ID: <425aqoF1hav5dU1@individual.net>
Joerg Hoehle wrote:
> Pascal Costanza <··@p-cos.net> writes:
> [no compiler-macrolet in ANSI CL]
> I presume it's due to the impossibility to portably assume that
>    (compiler-macrolet
>      code-that-shall-be-affected-by-it
> indeed will be processed at the time you presuppose it will.
> 
> There's a simple (naive) "interpretation" model of how compilation
> works, where such a constructs would make sense (i.e. recursively walk
> the source code).  But that's not the only model or implementation.  I
> believe that's why such a construct could not be kept in ANSI-CL.

Hm, maybe I am missing something important here, but ANSI-CL already has 
local macros - local compiler macros could "just" use the same model as 
the local macros, right?


Pascal

-- 
My website: http://p-cos.net
Closer to MOP & ContextL:
http://common-lisp.net/project/closer/
From: Kaz Kylheku
Subject: Re: Why no compiler-macrolet?
Date: 
Message-ID: <1136490539.467910.20870@g43g2000cwa.googlegroups.com>
Pascal Costanza wrote:
> What's the point in not allowing this?

I don't see anything not being allowed, just not being required. "There
is no provision for defining local compiler macros in the way macrolet
defines local macros".

So, it's the same point for why anything imaginable, that isn't
required, isn't required.

Note that COMPILER-MACRO-FUNCTION does take an optional environment
argument. That seems to anticipate an extension in which there could be
non-global environment macros.
From: Pascal Costanza
Subject: Re: Why no compiler-macrolet?
Date: 
Message-ID: <425bvkF1hjodmU1@individual.net>
Kaz Kylheku wrote:
> Pascal Costanza wrote:
> 
>>What's the point in not allowing this?
> 
> I don't see anything not being allowed, just not being required. "There
> is no provision for defining local compiler macros in the way macrolet
> defines local macros".

The previous sentence says that compiler macro definitions are strictly 
global. That's what caught my eye. (But maybe I misunderstand the 
subtleties of the English language here...)

> So, it's the same point for why anything imaginable, that isn't
> required, isn't required.
> 
> Note that COMPILER-MACRO-FUNCTION does take an optional environment
> argument. That seems to anticipate an extension in which there could be
> non-global environment macros.

That's, of course, better evidence. Thanks for spotting this...


Pascal

-- 
My website: http://p-cos.net
Closer to MOP & ContextL:
http://common-lisp.net/project/closer/
From: Duane Rettig
Subject: Re: Why no compiler-macrolet?
Date: 
Message-ID: <o0sls2nrk3.fsf@franz.com>
Pascal Costanza <··@p-cos.net> writes:

> Kaz Kylheku wrote:
>> Pascal Costanza wrote:
>>
>>>What's the point in not allowing this?
>> I don't see anything not being allowed, just not being
>> required. "There
>> is no provision for defining local compiler macros in the way macrolet
>> defines local macros".
>
> The previous sentence says that compiler macro definitions are
> strictly global. That's what caught my eye. (But maybe I misunderstand
> the subtleties of the English language here...)

I have read it the same way as you.  However, that only means that
a user cannot write portable code that assumes that there is any
way to define a compiler-macro - in essence, such code is
non-conforming.

>> So, it's the same point for why anything imaginable, that isn't
>> required, isn't required.
>> Note that COMPILER-MACRO-FUNCTION does take an optional environment
>> argument. That seems to anticipate an extension in which there could be
>> non-global environment macros.
>
> That's, of course, better evidence. Thanks for spotting this...

I don't think it's evidence of non-globality of a compiler-macro's
definition.  Instead, it provides a lexical environment that a (global)
compiler-macro could operate on.  It is the difference between:

(define-compiler-macro foo (&environment env ...)
  ...)

(defun bar (...)
  (foo ...))

(macrolet ((bas (...) ...))
  (foo ...))

where each expansion of foo is going to see a different lexical
environment,  vs the following hypothetical case:

(defun bam (x ...)
  (if x
      (xyz::compiler-macrolet ((foo (&environment env ...) ...))
        ...
        (foo ...)
        ...)
    (xyz::compiler-macrolet ((foo (&environment env ...) ...))
      ...
      (foo ...)
      ...)))

where each expansion of foo (different compiler-macros) presumably
gets the same environment.

Incidentally, I found it annoying to have the restriction of
compiler-macros being global only, when implementing the Environments
Access module - it made some of the coding clunky and not as smooth as
otherwise possible.  I can see why they are not provided for (because
there is no guarantee that a compiler-macro will in fact be invoked),
and I do believe that this is right and good.  However, the Environments
Access implementation provides a way to predict/control whether or
not a compiler-macro will be invoked, so among any implementations that
adhere to the Environments Access implementation, I could envision a
compiler-macrolet implementation (as an extension, of course, just as
E.A. is an extension) which uses that predictability and controllability
to provide portability across implementations that implement E.A.  (did
I mention that this was going to be a plug? :-)

-- 
Duane Rettig    ·····@franz.com    Franz Inc.  http://www.franz.com/
555 12th St., Suite 1450               http://www.555citycenter.com/
Oakland, Ca. 94607        Phone: (510) 452-2000; Fax: (510) 452-0182   
From: Pascal Costanza
Subject: Re: Why no compiler-macrolet?
Date: 
Message-ID: <426jg5F1gvmigU1@individual.net>
Duane Rettig wrote:
> Pascal Costanza <··@p-cos.net> writes:
> 
>>Kaz Kylheku wrote:
>>
>>>Pascal Costanza wrote:
>>>
>>>>What's the point in not allowing this?
>>>
>>>I don't see anything not being allowed, just not being
>>>required. "There
>>>is no provision for defining local compiler macros in the way macrolet
>>>defines local macros".
>>
>>The previous sentence says that compiler macro definitions are
>>strictly global. That's what caught my eye. (But maybe I misunderstand
>>the subtleties of the English language here...)
> 
> I have read it the same way as you.  However, that only means that
> a user cannot write portable code that assumes that there is any
> way to define a compiler-macro - in essence, such code is
> non-conforming.

OK, that's understood. However, I am more interested in the reason for 
this...

>>>So, it's the same point for why anything imaginable, that isn't
>>>required, isn't required.
>>>Note that COMPILER-MACRO-FUNCTION does take an optional environment
>>>argument. That seems to anticipate an extension in which there could be
>>>non-global environment macros.
>>
>>That's, of course, better evidence. Thanks for spotting this...
> 
> I don't think it's evidence of non-globality of a compiler-macro's
> definition.  Instead, it provides a lexical environment that a (global)
> compiler-macro could operate on.  It is the difference between:
> 
> (define-compiler-macro foo (&environment env ...)
>   ...)
> 
> (defun bar (...)
>   (foo ...))
> 
> (macrolet ((bas (...) ...))
>   (foo ...))
> 
> where each expansion of foo is going to see a different lexical
> environment,  vs the following hypothetical case:
> 
> (defun bam (x ...)
>   (if x
>       (xyz::compiler-macrolet ((foo (&environment env ...) ...))
>         ...
>         (foo ...)
>         ...)
>     (xyz::compiler-macrolet ((foo (&environment env ...) ...))
>       ...
>       (foo ...)
>       ...)))
> 
> where each expansion of foo (different compiler-macros) presumably
> gets the same environment.

Kaz was referring to the fact that 'compiler-macro-function takes an 
environment object as an optional second argument. This only makes sense 
if 'compiler-macro-function can potentially return different values 
based on that second argument, no?

> Incidentally, I found it annoying to have the restriction of
> compiler-macros being global only, when implementing the Environments
> Access module - it made some of the coding clunky and not as smooth as
> otherwise possible.  I can see why they are not provided for (because
> there is no guarantee that a compiler-macro will in fact be invoked),
> and I do believe that this is right and good.

Why? There is also no guarantee that global compiler macros will be 
invoked, so it'd be exactly the same.

> However, the Environments
> Access implementation provides a way to predict/control whether or
> not a compiler-macro will be invoked, so among any implementations that
> adhere to the Environments Access implementation, I could envision a
> compiler-macrolet implementation (as an extension, of course, just as
> E.A. is an extension) which uses that predictability and controllability
> to provide portability across implementations that implement E.A.  (did
> I mention that this was going to be a plug? :-)

No, but you haven't been very subtle either... ;)


Pascal

-- 
My website: http://p-cos.net
Closer to MOP & ContextL:
http://common-lisp.net/project/closer/
From: Thomas F. Burdick
Subject: Re: Why no compiler-macrolet?
Date: 
Message-ID: <xcv8xttmwm5.fsf@conquest.OCF.Berkeley.EDU>
Pascal Costanza <··@p-cos.net> writes:

> Duane Rettig wrote:
>
> > Incidentally, I found it annoying to have the restriction of
> > compiler-macros being global only, when implementing the Environments
> > Access module - it made some of the coding clunky and not as smooth as
> > otherwise possible.  I can see why they are not provided for (because
> > there is no guarantee that a compiler-macro will in fact be invoked),
> > and I do believe that this is right and good.
> 
> Why? There is also no guarantee that global compiler macros will be
> invoked, so it'd be exactly the same.

Duane's was the second response along these lines, and I don't
understand the reasoning either.  The way I view compiler macros is as
a mechanism of informing the implementation of a valid transformation.
Whether the compiler takes my advice or not is up to the compiler.  A
compiler-macrolet would be a very nice way to say, "here, this is a
valid tranformation only within the following lexical scope."

-- 
           /|_     .-----------------------.                        
         ,'  .\  / | Free Mumia Abu-Jamal! |
     ,--'    _,'   | Abolish the racist    |
    /       /      | death penalty!        |
   (   -.  |       `-----------------------'
   |     ) |                               
  (`-.  '--.)                              
   `. )----'                               
From: Duane Rettig
Subject: Re: Why no compiler-macrolet?
Date: 
Message-ID: <o0vewv531m.fsf@franz.com>
···@conquest.OCF.Berkeley.EDU (Thomas F. Burdick) writes:

> Pascal Costanza <··@p-cos.net> writes:
>
>> Duane Rettig wrote:
>>
>> > Incidentally, I found it annoying to have the restriction of
>> > compiler-macros being global only, when implementing the Environments
>> > Access module - it made some of the coding clunky and not as smooth as
>> > otherwise possible.  I can see why they are not provided for (because
>> > there is no guarantee that a compiler-macro will in fact be invoked),
>> > and I do believe that this is right and good.
>> 
>> Why? There is also no guarantee that global compiler macros will be
>> invoked, so it'd be exactly the same.
>
> Duane's was the second response along these lines, and I don't
> understand the reasoning either.  The way I view compiler macros is as
> a mechanism of informing the implementation of a valid transformation.
> Whether the compiler takes my advice or not is up to the compiler.  A
> compiler-macrolet would be a very nice way to say, "here, this is a
> valid tranformation only within the following lexical scope."

I think I should answer here before I attempt to answer Pascal in
another place on this thread (perhaps it will be complete enough
that I won't need two answers; Pascal, let me know if it doesn't
take care of all of your issues elsewhere):

I talked to Steve Haflich yesterday; he said he might answer on this
thread himself last night, but he is extremely busy right now and I
am assuming that he couldn't get a chance to answer at that time.
So I will do a dump of what I recall of our conversation.  I wanted
the opinion from someone who was actually there, and since Steve was
a co-writer of the define-compiler-macro writeup
(http://www.lisp.org/HyperSpec/Issues/iss101-writeup.html), it was
appropriate that I talked to him.

His first reaction to the simple question "why was there never
a `compiler-macrolet' introduced in the ansi process" was the same
as mine: the semantics were not guaranteed.  I mentioned some of the
issues that have been discussed here, and he said "Logically, it
probably should have been there, and it was mentioned, but nobody
wanted to step up to work out the semantics, which were going to be
tricky.  It just wasn't considered worth the risk of getting it
wrong".

He also mentioned some specifics:

 - We know that any lexical bindings for a function name will shadow
a compiler-macro definition, but if a macrolet were defined and 
a compiler-macrolet were defined inside the macrolet, which one
should be used for the expansion?  The general rules of lexical
scoping say that the compiler-macrolet is used.  But given the rule
that an implementation can choose to ignore a compiler-macro, is
the that really the equivalent of "uncovering" the shadowing of
the macrolet that the compiler-macrolet would do, or should the
shadowing of the compiler-macrolet be continued, and perhaps the
call to the function name be compiled just as a function call?
Perhaps you have an obvious take on what the answer should be, but
it is not a priori correct, and it would have to be weighed
aganst other possible interpretations of what is right.

 - He mentioned trouble with setf functions, and the trouble with
the assymetry of funtions and their setf counterparts, in terms of
both defining and using them.  I didn't write down his example, and
although I could probably work it out again, I don't want to mess it
up.  Note, however, that flet and labels allow for definition of
setf functions, but macrolet does not (its function name must be a
symbol).  If you work out why this is the case, you may stuble on
why there is a problem with the semantics of compiler-macrlolet on
a setf function name.

 - Anything that could be done with a compiler-macrolet form can also
be done with a macrolet form, and if the non-guaranteed-expansion
semantics of compiler-macros is still desired, then the macrolet
could easily be expanded into a form which is defined as a (global)
compiler-macro.

Steve summarized with the re-statement of the idea that perhaps it
should have been added, but nobody wanted to step up to work out
the semantics and risk getting those semantics wrong.

-- 
Duane Rettig    ·····@franz.com    Franz Inc.  http://www.franz.com/
555 12th St., Suite 1450               http://www.555citycenter.com/
Oakland, Ca. 94607        Phone: (510) 452-2000; Fax: (510) 452-0182   
From: Pascal Costanza
Subject: Re: Why no compiler-macrolet?
Date: 
Message-ID: <42ajslF1hrnthU1@individual.net>
Duane Rettig wrote:
> ···@conquest.OCF.Berkeley.EDU (Thomas F. Burdick) writes:
> 
>>Duane's was the second response along these lines, and I don't
>>understand the reasoning either.  The way I view compiler macros is as
>>a mechanism of informing the implementation of a valid transformation.
>>Whether the compiler takes my advice or not is up to the compiler.  A
>>compiler-macrolet would be a very nice way to say, "here, this is a
>>valid tranformation only within the following lexical scope."
> 
> I think I should answer here before I attempt to answer Pascal in
> another place on this thread (perhaps it will be complete enough
> that I won't need two answers; Pascal, let me know if it doesn't
> take care of all of your issues elsewhere):

Thanks - it starts to make much more sense now.

> I talked to Steve Haflich yesterday; he said he might answer on this
> thread himself last night, but he is extremely busy right now and I
> am assuming that he couldn't get a chance to answer at that time.
> So I will do a dump of what I recall of our conversation.  I wanted
> the opinion from someone who was actually there, and since Steve was
> a co-writer of the define-compiler-macro writeup
> (http://www.lisp.org/HyperSpec/Issues/iss101-writeup.html), it was
> appropriate that I talked to him.

Yes - and many greetings to him... ;)

> His first reaction to the simple question "why was there never
> a `compiler-macrolet' introduced in the ansi process" was the same
> as mine: the semantics were not guaranteed.  I mentioned some of the
> issues that have been discussed here, and he said "Logically, it
> probably should have been there, and it was mentioned, but nobody
> wanted to step up to work out the semantics, which were going to be
> tricky.  It just wasn't considered worth the risk of getting it
> wrong".

OK.

> He also mentioned some specifics:
> 
>  - We know that any lexical bindings for a function name will shadow
> a compiler-macro definition, but if a macrolet were defined and 
> a compiler-macrolet were defined inside the macrolet, which one
> should be used for the expansion?  The general rules of lexical
> scoping say that the compiler-macrolet is used.  But given the rule
> that an implementation can choose to ignore a compiler-macro, is
> the that really the equivalent of "uncovering" the shadowing of
> the macrolet that the compiler-macrolet would do, or should the
> shadowing of the compiler-macrolet be continued, and perhaps the
> call to the function name be compiled just as a function call?
> Perhaps you have an obvious take on what the answer should be, but
> it is not a priori correct, and it would have to be weighed
> aganst other possible interpretations of what is right.

Yes, I have an "obvious" take on this, but the devil is probably in the 
details.

>  - He mentioned trouble with setf functions, and the trouble with
> the assymetry of funtions and their setf counterparts, in terms of
> both defining and using them.  I didn't write down his example, and
> although I could probably work it out again, I don't want to mess it
> up.  Note, however, that flet and labels allow for definition of
> setf functions, but macrolet does not (its function name must be a
> symbol).  If you work out why this is the case, you may stuble on
> why there is a problem with the semantics of compiler-macrlolet on
> a setf function name.

I would be interested in this example - I'll see whether I can come up 
with it myself. I am aware that an flet on a non-setf function name 
shadows a global setf expander, so the problem is probably related to 
this, right?

>  - Anything that could be done with a compiler-macrolet form can also
> be done with a macrolet form, and if the non-guaranteed-expansion
> semantics of compiler-macros is still desired, then the macrolet
> could easily be expanded into a form which is defined as a (global)
> compiler-macro.

A first attempt of defining my own compiler-macrolet, where I tried to 
do something along these lines, wasn't really successful... :(

> Steve summarized with the re-statement of the idea that perhaps it
> should have been added, but nobody wanted to step up to work out
> the semantics and risk getting those semantics wrong.

...sounds like a late addition to the standard...


Thanks for you help,

Pascal

-- 
My website: http://p-cos.net
Closer to MOP & ContextL:
http://common-lisp.net/project/closer/
From: Steven M. Haflich
Subject: Re: Why no compiler-macrolet?
Date: 
Message-ID: <%t0wf.46476$BZ5.16476@newssvr13.news.prodigy.com>
As Duane mentioned, he asked me to append my thoughts, but I didn't
get around to it yesterday.  By the way, JonL and I were the authors
of the original compiler-macro X3J13 proposal.  We wrote it late one
evening during a 3-day committee meeting because we thought this was
an important facility in the language (for practical reasons, if not
theoretical) and if we didn't write it then it would not make it into
the language.

>> Steve summarized with the re-statement of the idea that perhaps it
>> should have been added, but nobody wanted to step up to work out
>> the semantics and risk getting those semantics wrong.

I don't remember that there was a _lot_ of discussion on the issue.
Since the addition of compiler macros was a rush job, no one had yet
formed informed opinions about the semantics.  There were several
subsequent revisions in details (see the Hyperspec issue writeup) but
at least we got it into the language.  When the issue of
compiler-macrolet arose, almost no one had any strong feelings and
absolutely no one had any experience with implementation.  So we
wisely let it drop.

My persional intuition is that compiler-macrolet _should_ be in the
language for reasons of consistency and regularity.  But it is not
important in any practical sense, and adding another special form to
the language isn't wise without practical experience using it.
Remember the various dyslexical special forms and markers in early
Lisp dialects.

Anyway, it is easy to devise examples of compiler-macrolet that raise
semantic issues.  For example, consdier the interaction with setf.

cl-user(1): (flet ((foo (x) (car x))
		   ((setf foo) (v x) (setf (car x) v)))
	      (let ((q (cons 'car 'cdr)))
		(setf (foo q) 'which)
		q))
(which . cdr)
cl-user(2): (flet ((foo (x) (car x))
		   ((setf foo) (v x) (setf (car x) v)))
	      (macrolet ((foo (x) `(cdr ,x)))
		(let ((q (cons 'car 'cdr)))
		  (setf (foo q) 'which)
		  q)))
(car . which)

I believe the above examples are required ANSI CI behavior.  In the
first the expansion of setf proceeds normally and in the absence of
any setf expander for foo, nor any macro definitiojn for foo, it
macroexpands into a call to (setf foo) which references the flet
binding.  (It would work the same if the definition of (setf foo) was
global.)  But in the second example there _is_ a visible macro
definition for foo, so the setf macro macroexpands the foo call.  In
effect the inner macrolet for foo shadows outer bindings of both foo
and (setf foo).

But what if the macrolet were replaced by compiler-macrolet?  If we
assume the compiler is free to ignore a compiler-macro, then the
semantics would not be well defined.  Setting either the car or the
cdr would be conformant.

Now imagine that the macrolet were replaced by compiler-macrolet.
What are the semantics?  If the compiler ignores the
compiler-macrolet, which it presumably is allowed to do, then the
flet of (setf foo) would be seen by setf as in [1] above.  But if the
compiler expands the compiler macro the form would execute as in [2].

One problem, of course, is the the ANS permits an implementation to
ignore compiler macros.  The reason is that in order to get the
committee to accept his new langage feature it had to be defined in
a way that permitted a trivial implementation.  But even if this
freedmo were removed, and all implementation were required to expand
cmopiler macros, there would still be the possibility that a compiler
macro would decline to expand (by returning &whole) which would lead
to a similar ambiguity.

There are other issues that would be raised by compiler-macrolet --
for instance, whether it would be allowed to place definition on
symbols in the CL package.  (Probably a bad idea.)  Because we
couldn't cnofidently survey _all_ the possible issues without first
implementing lexical compiler macros and living with them a few
years, I believe it was correct not to add them to the language.
Nonetheless, my intuition is that any semantic issues could be
understood and resolved given some time living with an actual
implementation.  As Duane has pointed out, any implementation is
free to add a xyz:compile-macrolet and see where it leads.
From: Thomas F. Burdick
Subject: Re: Why no compiler-macrolet?
Date: 
Message-ID: <xcvu0cfkn27.fsf@conquest.OCF.Berkeley.EDU>
Many thanks to both you and Duane for the detailed responses.

"Steven M. Haflich" <···@alum.mit.edu> writes:

> There are other issues that would be raised by compiler-macrolet --
> for instance, whether it would be allowed to place definition on
> symbols in the CL package.  (Probably a bad idea.)  Because we
> couldn't cnofidently survey _all_ the possible issues without first
> implementing lexical compiler macros and living with them a few
> years, I believe it was correct not to add them to the language.

This is a very good point.  I'd rather have the status-quo -- where we
can still figure out what the semantics should be in practice -- than
have a buggy compiler-macrolet mandated by the spec.

> Nonetheless, my intuition is that any semantic issues could be
> understood and resolved given some time living with an actual
> implementation.  As Duane has pointed out, any implementation is
> free to add a xyz:compile-macrolet and see where it leads.

Such a thing could obviously be added by users to the free Lisps, and
I think I could add it to MCL.  I know this is entirely the wrong
forum to be askin in, but could a user modify the appropriate
internals of Allegro's compiler?  Anyone know about Lispworks?

-- 
           /|_     .-----------------------.                        
         ,'  .\  / | Free Mumia Abu-Jamal! |
     ,--'    _,'   | Abolish the racist    |
    /       /      | death penalty!        |
   (   -.  |       `-----------------------'
   |     ) |                               
  (`-.  '--.)                              
   `. )----'                               
From: Pascal Costanza
Subject: Re: Why no compiler-macrolet?
Date: 
Message-ID: <42d9g5F1ht0jgU1@individual.net>
Steven M. Haflich wrote:
> As Duane mentioned, he asked me to append my thoughts, but I didn't
> get around to it yesterday.  By the way, JonL and I were the authors
> of the original compiler-macro X3J13 proposal.  We wrote it late one
> evening during a 3-day committee meeting because we thought this was
> an important facility in the language (for practical reasons, if not
> theoretical) and if we didn't write it then it would not make it into
> the language.

Thank you for taking your to respond.

> My persional intuition is that compiler-macrolet _should_ be in the
> language for reasons of consistency and regularity.  But it is not
> important in any practical sense, and adding another special form to
> the language isn't wise without practical experience using it.
> Remember the various dyslexical special forms and markers in early
> Lisp dialects.

I think it is important. Consider the example that I have already 
mentioned: A defmethod form has to expand into something like the following.

(defmethod m (...)
   ... (call-next-method) ...)

(add-method (fdefinition 'm)
   (make-instance 'standard-method
     ...
     :function (lambda (...)
                 (flet ((call-next-method (&rest args) ...))
                   ... (call-next-method) ...))))

In the general case, a local function for call-next-method is 
sufficient. However, IIUC it can be much more efficient if it can be 
implemnted as a macro - for example, if the method body doesn't use it 
as a first-class value (which is probably almost always the case).

(add-method (fdefinition 'm)
   (make-instance 'standard-method
     ...
     :function (lambda (...)
                 (macrolet ((call-next-method (&rest args) ...))
                   ... (call-next-method) ...))))

However, in order to know whether #'call-next-method is used as a 
first-class value or not, the implementation has to walk the whole 
method body. A local compiler-macro would be much more straightforward:

(add-method (fdefinition 'm)
   (make-instance 'standard-method
     ...
     :function (lambda (...)
                 (flet ((call-next-method (&rest args) ...))
                   (compiler-macrolet ((call-next-method (&rest args) ...))
                     ... (call-next-method) ...)))))

I don't know whether such cases occur often, but I think this is a valid 
case. (Something similar would have been useful in other CLOS MOP 
examples that I am playing around with.)

> Anyway, it is easy to devise examples of compiler-macrolet that raise
> semantic issues.  For example, consdier the interaction with setf.
> 
> cl-user(1): (flet ((foo (x) (car x))
>            ((setf foo) (v x) (setf (car x) v)))
>           (let ((q (cons 'car 'cdr)))
>         (setf (foo q) 'which)
>         q))
> (which . cdr)
> cl-user(2): (flet ((foo (x) (car x))
>            ((setf foo) (v x) (setf (car x) v)))
>           (macrolet ((foo (x) `(cdr ,x)))
>         (let ((q (cons 'car 'cdr)))
>           (setf (foo q) 'which)
>           q)))
> (car . which)
> 
> I believe the above examples are required ANSI CI behavior.  In the
> first the expansion of setf proceeds normally and in the absence of
> any setf expander for foo, nor any macro definitiojn for foo, it
> macroexpands into a call to (setf foo) which references the flet
> binding.  (It would work the same if the definition of (setf foo) was
> global.)  But in the second example there _is_ a visible macro
> definition for foo, so the setf macro macroexpands the foo call.  In
> effect the inner macrolet for foo shadows outer bindings of both foo
> and (setf foo).
[...]
> 
> Now imagine that the macrolet were replaced by compiler-macrolet.
> What are the semantics?  If the compiler ignores the
> compiler-macrolet, which it presumably is allowed to do, then the
> flet of (setf foo) would be seen by setf as in [1] above.  But if the
> compiler expands the compiler macro the form would execute as in [2].

My understanding of compiler macros is that they should strictly only be 
used for defining optimized versions of functions/macros. That's also 
how I understand the rationale for optionally omitting compiler macros 
(especially 3.2.2.1.3.1 in the HyperSpec). For this reason, the local 
compiler macro should, IMHO, not define any behavior that is different 
from the original function/macro in the first place. Then this wouldn't 
be an issue, and it seems to me that this is exactly the same as it 
would be for global compiler macros. Or what is the difference between 
your code and the following one?

(defun foo (x) (car x))

(defun (setf foo) (v x) (setf (car x) v))

(define-compiler-macro foo (x) `(cdr ,x))

> One problem, of course, is the the ANS permits an implementation to
> ignore compiler macros.  The reason is that in order to get the
> committee to accept his new langage feature it had to be defined in
> a way that permitted a trivial implementation.  But even if this
> freedmo were removed, and all implementation were required to expand
> cmopiler macros, there would still be the possibility that a compiler
> macro would decline to expand (by returning &whole) which would lead
> to a similar ambiguity.

...also if the function is declared notinline, and I would also expect 
compiler macros not be expanded if compilation-speed is set to a high value.

> There are other issues that would be raised by compiler-macrolet --
> for instance, whether it would be allowed to place definition on
> symbols in the CL package.  (Probably a bad idea.)

...and already excluded in 11.1.2.1.2

> Because we
> couldn't cnofidently survey _all_ the possible issues without first
> implementing lexical compiler macros and living with them a few
> years, I believe it was correct not to add them to the language.

This makes sense.

> Nonetheless, my intuition is that any semantic issues could be
> understood and resolved given some time living with an actual
> implementation.  As Duane has pointed out, any implementation is
> free to add a xyz:compile-macrolet and see where it leads.

OK, thanks again,
Pascal

-- 
My website: http://p-cos.net
Closer to MOP & ContextL:
http://common-lisp.net/project/closer/
From: Thomas F. Burdick
Subject: Re: Why no compiler-macrolet?
Date: 
Message-ID: <xcvy81pkaev.fsf@conquest.OCF.Berkeley.EDU>
Pascal Costanza <··@p-cos.net> writes:

> Steven M. Haflich wrote:
> 
> > My persional intuition is that compiler-macrolet _should_ be in the
> > language for reasons of consistency and regularity.  But it is not
> > important in any practical sense, and adding another special form to
> > the language isn't wise without practical experience using it.
> > Remember the various dyslexical special forms and markers in early
> > Lisp dialects.
> 
> I think it is important. Consider the example that I have already
> mentioned: A defmethod form has to expand into something like the
> following.
> 
> (defmethod m (...)
>    ... (call-next-method) ...)
> 
> (add-method (fdefinition 'm)
>    (make-instance 'standard-method
>      ...
>      :function (lambda (...)
>                  (flet ((call-next-method (&rest args) ...))
>                    ... (call-next-method) ...))))
> 
> In the general case, a local function for call-next-method is
> sufficient. However, IIUC it can be much more efficient if it can be
> implemnted as a macro - for example, if the method body doesn't use it
> as a first-class value (which is probably almost always the case).

I don't think this is a terribly convincing example, because
optimizations like inlining local functions are the type of thing I'd
expect the compiler to handle.

-- 
           /|_     .-----------------------.                        
         ,'  .\  / | Free Mumia Abu-Jamal! |
     ,--'    _,'   | Abolish the racist    |
    /       /      | death penalty!        |
   (   -.  |       `-----------------------'
   |     ) |                               
  (`-.  '--.)                              
   `. )----'                               
From: Duane Rettig
Subject: Re: Why no compiler-macrolet?
Date: 
Message-ID: <o0hd8hgqqk.fsf@franz.com>
Pascal Costanza <··@p-cos.net> writes:

> Duane Rettig wrote:
>> Pascal Costanza <··@p-cos.net> writes:
>>
>>>Kaz Kylheku wrote:
>>>
>>>>Pascal Costanza wrote:
>>>>
>>>>>What's the point in not allowing this?
>>>>
>>>>I don't see anything not being allowed, just not being
>>>>required. "There
>>>>is no provision for defining local compiler macros in the way macrolet
>>>>defines local macros".
>>>
>>>The previous sentence says that compiler macro definitions are
>>>strictly global. That's what caught my eye. (But maybe I misunderstand
>>>the subtleties of the English language here...)
>> I have read it the same way as you.  However, that only means that
>> a user cannot write portable code that assumes that there is any
>> way to define a compiler-macro - in essence, such code is
>> non-conforming.
>
> OK, that's understood. However, I am more interested in the reason for
> this...

If you can stretch your imagination to analogize compiler-macros as
if they were simply an extension to declarations, then what we know
and can assume about declarations can clarify what we know and assume
about compiler-macros:

First, with the exceptions of SPECIAL, NOTINLINE, and DECLARATION
declarations, which must always be obeyed (plus the SAFETY optimization
quality under certain circumstances) all other declarations can be
ignored by an implementation.  What is the reason for this?  Well, you
can draw your own conclusions, but my view is that it is so that
implementations can, if desired, perform minimal work to accomplish the
goal of compilation or interpretation of lisp code.  And, indeed, in
eval implementations that employ interpreters, declarations tend to be
ignored.  However, for high-end, competitive compilation efforts, of
course it behooves a compiler to do as much as it can with compilation
information, so as to remain competitive.

Now, how can declarations get one into trouble in the area of
portability?  It is due to a concept I call "lying to the compiler"
(I use the pejorative term rather than something more euphemistic,
like "casting" or "aliasing" or even "fudging", because I am a compiler
writer, and although I use the technique myself, I'd rather call it what
it really is).  Let's try a simple example: I have two octet vectors
of size 4 each, and I want to do the fastest comparison possible
between the two.  The code would be

(defun compare-four-byte-vectors (x y)
  (declare (optimize speed) ((simple-array (signed-byte 32) (4)) x y))
  (= (aref x 0) (aref y 0)))

Note that this function only "works" as expected if compiled - if two
(signed-byte 8) or (unsigned-byte 8) vectors of at least four bytes
each are passed in, it will compare the first four bytes of the vectors.
However, if this function is left uncompiled, _or_ if the compiler
chooses to ignore the declarations (which it is perfectly in its rights
to do) then the function fails; only the first byte of each vector is
compared.

Generally, lying to the compiler should be discouraged.  However, there
are places where it is useful for efficiency to tell the compiler
enough for it to perform the goal at hand, but not so much that the
compiler throttles the effort.  (note that life in general is much
more complex than a Lisp compiler, and I do not advocate lying in
real life situations...)


Now, let's move this to the realm of compiler-macros.  Consider the
following definition:

(defun foo (x y)
   (+ x y))

and the following _lie_:

(define-compiler-macro foo (x y)
  `(- ,x ,y))

[why do I call it a lie?  Because a compiler-macro is intended to
optimize the functionality already defined in a function or macro,
and if that functionality is _different_ than the real definition,
then the difference in behavior is detectible by the proper outside
stimulus, as is the case with a lie.]

Perhaps you can see where this is going - If I then define a function:

(defun bar (x y)
   (foo x y))

what is the result of (bar 10 5)?  The answer:  maybe 15, maybe 5,
but not predictable.  Questions needed for the prediction: Is bar
compiled?  Does the compiler expand compiler-macros?  Was the
compiler-macro even defined before bar was compiled?

I don't know if I've gone far enough to provide a substrate for
thinking about compiler-macros, and the why of their unspecified
nature.  Perhaps I've written too much.  More could probably be
written, and I'm sure others could give examples of where this
is dangerous, and where it comes in handy.


>>>>So, it's the same point for why anything imaginable, that isn't
>>>>required, isn't required.
>>>>Note that COMPILER-MACRO-FUNCTION does take an optional environment
>>>>argument. That seems to anticipate an extension in which there could be
>>>>non-global environment macros.
>>>
>>>That's, of course, better evidence. Thanks for spotting this...

[irrelevant example elided ... ]

> Kaz was referring to the fact that 'compiler-macro-function takes an
> environment object as an optional second argument. This only makes
> sense if 'compiler-macro-function can potentially return different
> values based on that second argument, no?

Yes, sorry - brain fart.

But are all environment arguments lexical?  Or is the only global
environment the null environment?  What if the lisp has one
compiler-macro definition globally for foo, and a file bar.cl is
being compiled which contains a define-compiler-macro - what should
compiler-macro-function return then - the global definition, or the
one currently shadowing the global one in the compile-file's
global environment?

>> Incidentally, I found it annoying to have the restriction of
>> compiler-macros being global only, when implementing the Environments
>> Access module - it made some of the coding clunky and not as smooth as
>> otherwise possible.  I can see why they are not provided for (because
>> there is no guarantee that a compiler-macro will in fact be invoked),
>> and I do believe that this is right and good.
>
> Why? There is also no guarantee that global compiler macros will be
> invoked, so it'd be exactly the same.

In my Environments Access module, I provide a substrate and a recommendation
for the expansion of compiler-macros:  I create an extended environment
type called a "compiler" environment (as opposed to a "compilation"
environment, as mandated by the spec) - a compiler environment is a
compilation environment, but not vice versa, and compiler environments
are the exclusive environments within which compiler-macros are expanded.
An implementation that embraces Environments Access is free to either
establish compiler-environments by the compiler, or to establish
compilation environments.  In the former case, compiler-macros will be
expanded (i.e. when seen by a compiler environment) and in the latter
case, they will not.  Not necessarily portable, but entirely predictable,
and so portable code can be created.

>> However, the Environments
>> Access implementation provides a way to predict/control whether or
>> not a compiler-macro will be invoked, so among any implementations that
>> adhere to the Environments Access implementation, I could envision a
>> compiler-macrolet implementation (as an extension, of course, just as
>> E.A. is an extension) which uses that predictability and controllability
>> to provide portability across implementations that implement E.A.  (did
>> I mention that this was going to be a plug? :-)
>
> No, but you haven't been very subtle either... ;)

:-)

-- 
Duane Rettig    ·····@franz.com    Franz Inc.  http://www.franz.com/
555 12th St., Suite 1450               http://www.555citycenter.com/
Oakland, Ca. 94607        Phone: (510) 452-2000; Fax: (510) 452-0182   
From: Pascal Costanza
Subject: Re: Why no compiler-macrolet?
Date: 
Message-ID: <427se6F1gf7ucU1@individual.net>
Duane Rettig wrote:
> Pascal Costanza <··@p-cos.net> writes:
> 
>>Duane Rettig wrote:
>>
>>>Pascal Costanza <··@p-cos.net> writes:
>>>
>>>>Kaz Kylheku wrote:
>>>>
>>>>>Pascal Costanza wrote:
>>>>>
>>>>>>What's the point in not allowing this?
>>>>>
>>>>>I don't see anything not being allowed, just not being
>>>>>required. "There
>>>>>is no provision for defining local compiler macros in the way macrolet
>>>>>defines local macros".
>>>>
>>>>The previous sentence says that compiler macro definitions are
>>>>strictly global. That's what caught my eye. (But maybe I misunderstand
>>>>the subtleties of the English language here...)
>>>
>>>I have read it the same way as you.  However, that only means that
>>>a user cannot write portable code that assumes that there is any
>>>way to define a compiler-macro - in essence, such code is
>>>non-conforming.
>>
>>OK, that's understood. However, I am more interested in the reason for
>>this...
> 
[...]
> I don't know if I've gone far enough to provide a substrate for
> thinking about compiler-macros, and the why of their unspecified
> nature.  Perhaps I've written too much.  More could probably be
> written, and I'm sure others could give examples of where this
> is dangerous, and where it comes in handy.

Thanks a lot for the explanation. However, I have the strong feeling 
that we are talking at cross-purposes here. I have been completely aware 
of the fact that compiler macros can be ignored by a Common Lisp 
implementation. What I am wondering about is this: Why am I allowed to 
write the following...

(defun f (x)
   (* 2 x))

(define-compiler-macro f (x)
   `(* 2 ,x))

...but not the following...

(flet ((f (x) (* 2 x)))
   (compiler-macrolet ((f (x) `(* 2 ,x)))
     ...))

?

The wording in ANSI CL seems to indicate that there was a good reason 
not to include such a facility, and I would be interested to hear more 
about it. I can't imagine any problems with local compiler macros that 
go substantially beyond the potential problems of global compiler macros.

>>Kaz was referring to the fact that 'compiler-macro-function takes an
>>environment object as an optional second argument. This only makes
>>sense if 'compiler-macro-function can potentially return different
>>values based on that second argument, no?
> 
> Yes, sorry - brain fart.
> 
> But are all environment arguments lexical?  Or is the only global
> environment the null environment?  What if the lisp has one
> compiler-macro definition globally for foo, and a file bar.cl is
> being compiled which contains a define-compiler-macro - what should
> compiler-macro-function return then - the global definition, or the
> one currently shadowing the global one in the compile-file's
> global environment?

Ah, I wasn't aware that there can be multiple global environments. 
Interesting.

>>>Incidentally, I found it annoying to have the restriction of
>>>compiler-macros being global only, when implementing the Environments
>>>Access module - it made some of the coding clunky and not as smooth as
>>>otherwise possible.  I can see why they are not provided for (because
>>>there is no guarantee that a compiler-macro will in fact be invoked),
>>>and I do believe that this is right and good.
>>
>>Why? There is also no guarantee that global compiler macros will be
>>invoked, so it'd be exactly the same.
> 
> In my Environments Access module, I provide a substrate and a recommendation
> for the expansion of compiler-macros:  I create an extended environment
> type called a "compiler" environment (as opposed to a "compilation"
> environment, as mandated by the spec) - a compiler environment is a
> compilation environment, but not vice versa, and compiler environments
> are the exclusive environments within which compiler-macros are expanded.
> An implementation that embraces Environments Access is free to either
> establish compiler-environments by the compiler, or to establish
> compilation environments.  In the former case, compiler-macros will be
> expanded (i.e. when seen by a compiler environment) and in the latter
> case, they will not.  Not necessarily portable, but entirely predictable,
> and so portable code can be created.

Er, and how does this explain why there are no local compiler macros?!? 
I am completely lost here...


Pascal

-- 
My website: http://p-cos.net
Closer to MOP & ContextL:
http://common-lisp.net/project/closer/
From: Christophe Rhodes
Subject: Re: Why no compiler-macrolet?
Date: 
Message-ID: <sq8xttypgv.fsf@cam.ac.uk>
Duane Rettig <·····@franz.com> writes:

> Let's try a simple example: I have two octet vectors
> of size 4 each, and I want to do the fastest comparison possible
> between the two.  The code would be
>
> (defun compare-four-byte-vectors (x y)
>   (declare (optimize speed) ((simple-array (signed-byte 32) (4)) x y))
>   (= (aref x 0) (aref y 0)))

Why is this in any way better than
  (defun compare-four-byte-vectors (x y)
    (= (%mem-ref-32 x) (%mem-ref-32 y)))
or whatever is the local equivalent?  That is, I cannot see any
motivation for this lie at all, even if you do control the compiler.

Christophe
From: Duane Rettig
Subject: Re: Why no compiler-macrolet?
Date: 
Message-ID: <o0sls0by1p.fsf@franz.com>
Christophe Rhodes <·····@cam.ac.uk> writes:

> Duane Rettig <·····@franz.com> writes:
>
>> Let's try a simple example: I have two octet vectors
>> of size 4 each, and I want to do the fastest comparison possible
>> between the two.  The code would be
>>
>> (defun compare-four-byte-vectors (x y)
>>   (declare (optimize speed) ((simple-array (signed-byte 32) (4)) x y))
>>   (= (aref x 0) (aref y 0)))
>
> Why is this in any way better than
>   (defun compare-four-byte-vectors (x y)
>     (= (%mem-ref-32 x) (%mem-ref-32 y)))
> or whatever is the local equivalent?  That is, I cannot see any
> motivation for this lie at all, even if you do control the compiler.

Seems to me that this %mem-ref-32 would be a "lie", also.  What would

(let ((x (make-array 4 :element-type '(unsigned-byte 8))))
  (%mem-ref-32 x))

return?

What would it return on a machine of the opposite endianness?

-- 
Duane Rettig    ·····@franz.com    Franz Inc.  http://www.franz.com/
555 12th St., Suite 1450               http://www.555citycenter.com/
Oakland, Ca. 94607        Phone: (510) 452-2000; Fax: (510) 452-0182   
From: Duane Rettig
Subject: Re: Why no compiler-macrolet?
Date: 
Message-ID: <o0oe2obxww.fsf@franz.com>
[sorry; bad code alert: corrected code below]

Christophe Rhodes <·····@cam.ac.uk> writes:

> Duane Rettig <·····@franz.com> writes:
>
>> Let's try a simple example: I have two octet vectors
>> of size 4 each, and I want to do the fastest comparison possible
>> between the two.  The code would be
>>
>> (defun compare-four-byte-vectors (x y)
>>   (declare (optimize speed) ((simple-array (signed-byte 32) (4)) x y))
>>   (= (aref x 0) (aref y 0)))
>
> Why is this in any way better than
>   (defun compare-four-byte-vectors (x y)
>     (= (%mem-ref-32 x) (%mem-ref-32 y)))
> or whatever is the local equivalent?  That is, I cannot see any
> motivation for this lie at all, even if you do control the compiler.

Seems to me that this %mem-ref-32 would be a "lie", also.  What would

(let ((x (make-array 4 :element-type '(unsigned-byte 8)
                       :initial-contents '(1 2 3 4))))
  (%mem-ref-32 x))

return?

What would it return on a machine of the opposite endianness?

-- 
Duane Rettig    ·····@franz.com    Franz Inc.  http://www.franz.com/
555 12th St., Suite 1450               http://www.555citycenter.com/
Oakland, Ca. 94607        Phone: (510) 452-2000; Fax: (510) 452-0182   
From: Cameron MacKinnon
Subject: C-like Unions in Lisp (was Re: Why no compiler-macrolet?)
Date: 
Message-ID: <43bf3072$0$15790$14726298@news.sunsite.dk>
Duane Rettig wrote:
> Christophe Rhodes <·····@cam.ac.uk> writes:
> 
>>Duane Rettig <·····@franz.com> writes:
>>
>>>Let's try a simple example: I have two octet vectors
>>>of size 4 each, and I want to do the fastest comparison possible
>>>between the two.  The code would be
>>>
>>>(defun compare-four-byte-vectors (x y)
>>>  (declare (optimize speed) ((simple-array (signed-byte 32) (4)) x y))
>>>  (= (aref x 0) (aref y 0)))
>>
>>Why is this in any way better than
>>  (defun compare-four-byte-vectors (x y)
>>    (= (%mem-ref-32 x) (%mem-ref-32 y)))
>>or whatever is the local equivalent?  That is, I cannot see any
>>motivation for this lie at all, even if you do control the compiler.
> 
> 
> Seems to me that this %mem-ref-32 would be a "lie", also.  What would
> 
> (let ((x (make-array 4 :element-type '(unsigned-byte 8)
>                        :initial-contents '(1 2 3 4))))
>   (%mem-ref-32 x))
> 
> return?
> 
> What would it return on a machine of the opposite endianness?

That's a bit unfair. Your initial code relied on intimate implementation 
knowledge, as did Christophe's. Either would have worked in any endian 
environment.

I've been thinking a lot about coding things similar to the above in 
(un-Common) Lisp, e.g. fast processing which would typically require 
casting and/or unions in C. Take network packets: Typically we have a 
header consisting of various fields in widths from 32 bits down to one 
or two, perhaps another header depending on the values in the first, 
then a body which might be interpreted as a series of 16 bit values (as 
part of a checksum calculation) and simultaneously as a series of octets 
-- data which will be passed to a higher protocol, which might impose 
its own structural conventions.

It isn't that I want to lie to the compiler, but I want to express a 
duality which CL doesn't allow me to express. I don't want to process 
things a byte at a time, pairing them to perform the checksum, nor do I 
want to process them 16 bits at a time, adding code to process each half 
of the octet pair. Ideally, I want to process the same data both octet- 
and halfword-at-a-time. For bonus points, it'd be nice if this were all 
distilled down into modern SIMD instructions where possible.

I understand how this is totally outside the mandate of CL, and why 
that's so. But I thought I'd ask about previous approaches to this 
problem, and with two compiler writers discussing a germane topic, this 
seemed like the time.

So in summary:

What are the approaches to this 'data duality' problem? Can anyone point 
me to particularly elegant or 'good' approaches to the problem in the 
broader Lisp community? I haven't studied implementations' guts, as yet, 
but do have LiSP on order (might that help?)

As I touched on above, I see effective use of SIMD instructions as a 
related problem. Do people have pointers for me to assist in my very 
limited understanding? Papers? Particularly useful low-level-lisp 
implementations?
From: Duane Rettig
Subject: Re: C-like Unions in Lisp (was Re: Why no compiler-macrolet?)
Date: 
Message-ID: <o03bk0550y.fsf@franz.com>
Cameron MacKinnon <··········@clearspot.net> writes:

> Duane Rettig wrote:
>> Christophe Rhodes <·····@cam.ac.uk> writes:
>>
>>>Duane Rettig <·····@franz.com> writes:
>>>
>>>>Let's try a simple example: I have two octet vectors
>>>>of size 4 each, and I want to do the fastest comparison possible
>>>>between the two.  The code would be
>>>>
>>>>(defun compare-four-byte-vectors (x y)
>>>>  (declare (optimize speed) ((simple-array (signed-byte 32) (4)) x y))
>>>>  (= (aref x 0) (aref y 0)))
>>>
>>>Why is this in any way better than
>>>  (defun compare-four-byte-vectors (x y)
>>>    (= (%mem-ref-32 x) (%mem-ref-32 y)))
>>>or whatever is the local equivalent?  That is, I cannot see any
>>>motivation for this lie at all, even if you do control the compiler.
>> Seems to me that this %mem-ref-32 would be a "lie", also.  What would
>> (let ((x (make-array 4 :element-type '(unsigned-byte 8)
>>                        :initial-contents '(1 2 3 4))))
>>   (%mem-ref-32 x))
>> return?
>> What would it return on a machine of the opposite endianness?
>
> That's a bit unfair.

Harsh, perhaps, but not unfair.  Note that I am equally harsh on
myself for the lie, which I could have instead called "aliasing"
or "casting".  Note also that I tell the lie quite often.  No, not
unfair at all.

>  Your initial code relied on intimate
> implementation knowledge, as did Christophe's. Either would have
> worked in any endian environment.

Right, making it a "safe lie", as it were (though the only "intimate
knowledge" needed here, which is that the two kinds of arrays are located
in the same place, is not so very intimate).  But both of our lies
were essentially equivalent, using the co-location of the first four
bytes of similar vectors to alias the different data widths.

> I've been thinking a lot about coding things similar to the above in
> (un-Common) Lisp, e.g. fast processing which would typically require
> casting and/or unions in C. Take network packets: Typically we have a
> header consisting of various fields in widths from 32 bits down to one
> or two, perhaps another header depending on the values in the first,
> then a body which might be interpreted as a series of 16 bit values
> (as part of a checksum calculation) and simultaneously as a series of
> octets -- data which will be passed to a higher protocol, which might
> impose its own structural conventions.
>
> It isn't that I want to lie to the compiler, but I want to express a
> duality which CL doesn't allow me to express. I don't want to process
> things a byte at a time, pairing them to perform the checksum, nor do
> I want to process them 16 bits at a time, adding code to process each
> half of the octet pair. Ideally, I want to process the same data both
> octet-
> and halfword-at-a-time.

We have promoted this kind of thing for a long time:

 - Our "foreign types" interface need not be used only for foreign types,
but is very useful for manipulation of such unions and foreign-like
structs.  For example, we use it to parse the PE (portable executable)
file format for getting symbolic information out of .dll files in
a windows application.  Parts of the file are read into these foreign
structures, which might just be octet vectors with type templates
overlayed on them.  For more infor on foreign types, see
http://www.franz.com/support/documentation/7.0/doc/ftype.htm

 - Even before we created simple-streams, we had a concept of "bivalent"
streams, on which either read-char or read-byte would work.  When
we went to simple-streams, we extended this concept to "multivalent"
streams, where not only the binary-vs-character orientation of the
stream was comingled, but also various widths of binary stream could
also be comingled, with a new function called read-vector - similar
to read-sequence except that it reads octets into whatever structures
receive it, rather than reading element-at-a-time.  Thus, if you have
a file with 100 bytes in it, and you have two vectors, one
(unsigned-byte 32) vector of 16 elements and an (unsigned-byte 8)
vector of 36 elements, you could do two read-vectors into these
vectors respectively and use up exactly the entire file.  Or, instead,
you could read-vector the file into a foreign struct of various fields
and formats, and lay out as many bytes as are represented in the
structure.  And, as I presume all CLs with good FFIs do, we have exensive
test suites that ensure that the sizes and alignments of foreign structs
in the target C/C++ compilers correspond to what the lisp foreign structs
side thinks, and we have fairly extensive regression tests to ensure
that they remain in sync.

> For bonus points, it'd be nice if this were
> all distilled down into modern SIMD instructions where possible.

Well, yes, that would be a bonus, but I don't know of any automatic
parallelization to simd instructions - generally, one has to access
the instructions directly currently.  Of course, any scalar use of
the parallel hardware is going to be automatic, e.g. the scalar use
of SSE/SSE2 instructions for doing all floating point on x86-64
systems.

> I understand how this is totally outside the mandate of CL, and why
> that's so. But I thought I'd ask about previous approaches to this
> problem, and with two compiler writers discussing a germane topic,
> this seemed like the time.

Any time is the right time to ask a question.

> So in summary:
>
> What are the approaches to this 'data duality' problem? Can anyone
> point me to particularly elegant or 'good' approaches to the problem
> in the broader Lisp community? I haven't studied implementations'
> guts, as yet, but do have LiSP on order (might that help?)

What is "LiSP"?  A book?  Crys of lack of books by the Lisp community
notwithstanding, there are simply too many Lisp books out there to
know which one you are talking about, without an author and or the
complete name of the book.  Perhaps there is a book with just the
title "LiSP", but I don't know it, nor do I know if perhaps there
was a typo in your description.

As for data duality approaches, I think I have answered that to at least
a small degree, above.

> As I touched on above, I see effective use of SIMD instructions as a
> related problem. Do people have pointers for me to assist in my very
> limited understanding? Papers? Particularly useful low-level-lisp
> implementations?

None here.  We've looked at the problem often, as early back as
1988/1989, when we finished our first Cray port and Cray Research
asked us to start researching such manual and automatic simd
parallelization (also simply called "vectorization"), but the money
dried up when Cray started having to turn its attentions elsewhere.
We've considered automatic vectorization off and on for many years,
but Amdahl's Law is still a stumbling block except in very specific
application areas.

-- 
Duane Rettig    ·····@franz.com    Franz Inc.  http://www.franz.com/
555 12th St., Suite 1450               http://www.555citycenter.com/
Oakland, Ca. 94607        Phone: (510) 452-2000; Fax: (510) 452-0182   
From: Juho Snellman
Subject: Re: C-like Unions in Lisp (was Re: Why no compiler-macrolet?)
Date: 
Message-ID: <slrndrvuf0.523.jsnell@sbz-30.cs.Helsinki.FI>
Duane Rettig <·····@franz.com> wrote:
> Cameron MacKinnon <··········@clearspot.net> writes:
>> What are the approaches to this 'data duality' problem? Can anyone
>> point me to particularly elegant or 'good' approaches to the problem
>> in the broader Lisp community? I haven't studied implementations'
>> guts, as yet, but do have LiSP on order (might that help?)
> 
> What is "LiSP"?  A book? [...]

_Lisp in Small Pieces_ by Christian Queinnec.

-- 
Juho Snellman
From: Duane Rettig
Subject: Re: C-like Unions in Lisp (was Re: Why no compiler-macrolet?)
Date: 
Message-ID: <o0r77j530c.fsf@franz.com>
Juho Snellman <······@iki.fi> writes:

> Duane Rettig <·····@franz.com> wrote:
>> Cameron MacKinnon <··········@clearspot.net> writes:
>>> What are the approaches to this 'data duality' problem? Can anyone
>>> point me to particularly elegant or 'good' approaches to the problem
>>> in the broader Lisp community? I haven't studied implementations'
>>> guts, as yet, but do have LiSP on order (might that help?)
>> 
>> What is "LiSP"?  A book? [...]
>
> _Lisp in Small Pieces_ by Christian Queinnec.

Thanks, forgot about that one.

-- 
Duane Rettig    ·····@franz.com    Franz Inc.  http://www.franz.com/
555 12th St., Suite 1450               http://www.555citycenter.com/
Oakland, Ca. 94607        Phone: (510) 452-2000; Fax: (510) 452-0182   
From: Joerg Hoehle
Subject: Re: Why no compiler-macrolet?
Date: 
Message-ID: <ubqyalo28.fsf@users.sourceforge.net>
Pascal Costanza <··@p-cos.net> writes:
> Kaz Kylheku wrote:
> > Note that COMPILER-MACRO-FUNCTION does take an optional environment
> > argument. That seems to anticipate an extension in which there could be
> > non-global environment macros.
> That's, of course, better evidence. Thanks for spotting this...

That's nonsense (Kaz, please excuse :).  The expander needs the
environment information as much as any defmacro expander does.

Regards,
	Jorg Hohle
Telekom/T-Systems Technology Center
From: Kaz Kylheku
Subject: Re: Why no compiler-macrolet?
Date: 
Message-ID: <1137536146.843317.295010@g49g2000cwa.googlegroups.com>
Joerg Hoehle wrote:
> Pascal Costanza <··@p-cos.net> writes:
> > Kaz Kylheku wrote:
> > > Note that COMPILER-MACRO-FUNCTION does take an optional environment
> > > argument. That seems to anticipate an extension in which there could be
> > > non-global environment macros.
> > That's, of course, better evidence. Thanks for spotting this...
>
> That's nonsense (Kaz, please excuse :).  The expander needs the
> environment information as much as any defmacro expander does.

Ah that's true, since the expression being expanded can contain
subexpressions. The main expression may be expanded by a global macro,
but if that macro needs to macroexpand subexpressions, it needs to pass
through the environment.