From: Peter Seibel
Subject: Why multiple-value-prog1?
Date: 
Message-ID: <m3of282gnu.fsf@javamonkey.com>
I was wondering why MULTIPLE-VALUE-PROG1 existed--i.e. why doesn't
PROG1 just propogate multiple values the way PROGN does. So I googled
around a bit and found this quote from Erik Naggum (Message-ID:
<················@naggum.net>):

  You may want to use multiple-value-prog1 here, which is a gratuitous
  invasion of multiple value. prog1 should have preserved multiple
  values to begin with, just like :after methods, unwind-protect, etc,
  do.

So, buoyed by this knowledge that wiser heads than mine have found the
existence of MULTIPLE-VALUE-PROG1 strange or unfortunate, I'm
emboldened to ask: why? I assume that the answer is historical. As
always, I'm interested in that history.

-Peter

-- 
Peter Seibel                                      ·····@javamonkey.com

  The intellectual level needed   for  system design is  in  general
  grossly  underestimated. I am  convinced  more than ever that this
  type of work is very difficult and that every effort to do it with
  other than the best people is doomed to either failure or moderate
  success at enormous expense. --Edsger Dijkstra

From: Kaz Kylheku
Subject: Re: Why multiple-value-prog1?
Date: 
Message-ID: <cf333042.0305121238.66d2728b@posting.google.com>
Peter Seibel <·····@javamonkey.com> wrote in message news:<··············@javamonkey.com>...
> I was wondering why MULTIPLE-VALUE-PROG1 existed--i.e. why doesn't
> PROG1 just propogate multiple values the way PROGN does.

It exists probably as an optimization mechanism pushed on to the
programmer. When the programmer writes MULTIPLE-VALUE-PROG1, it's a
signal to the compiler that the programmer cares about the multiple
values. So no analysis needs to be performed to eliminate them.

If there was just PROG1, with multiple value semantics, then an
optimized PROG1 would have to determine whether or not keep the stash
of multiple values or not, based on the context in which that form
appears. There are contexts in which a pessimistic assumption must be
made that the multiple values *are* needed, and no further analysis
can be performed (like the last expression in the implicit PROGN that
constitutes a function body).

On the other hand, PROGN (and implicit PROGN) clobbered multiple
values, it would be a disaster, because straightforward Lisp code
would become opaque to the passage of multiple values. But PROG1 is
used rarely, and is always explicit, so that its behavior does not
give rise to a rampant spread of MV-unfriendly code.

But since PROG1 is used rarely, it should promote correctness, rater
than optimization. It's the optimized version of PROG1 that should
have the longer, more inconvenient name. That is to say, it would be a
better design if PROG1 passed multiple values; and to help the
compiler in hard-to-analyze cases when those values are not desired,
there could be a SINGLE-VALUE-PROG1.

This keeps with the principle that the most straightforward, terse
Lisp code should do The Right Thing even if there is a performance
penalty. Special versions of functions or operators, or additional
declarations or other verbiage, should be needed for optimization, not
to override bad defaults in order to obtain robust behavior.
From: Barry Margolin
Subject: Re: Why multiple-value-prog1?
Date: 
Message-ID: <1ISva.22$293.1049@paloalto-snr1.gtei.net>
In article <··············@javamonkey.com>,
Peter Seibel  <·····@javamonkey.com> wrote:
>I was wondering why MULTIPLE-VALUE-PROG1 existed--i.e. why doesn't
>PROG1 just propogate multiple values the way PROGN does.

It simplifies the implementation if it knows how many values it has to
save.  The code generated for PROG1 just has to reserve a single register
or stack location, rather than deal with arbitrary numbers of values
(perhaps by consing a list).  E.g. it can be:

(defmacro prog1 (form1 &rest forms)
  (let ((saved-value ,form1))
    ,@forms
    saved-value))

(defmacro multiple-value-prog1 (form1 &rest forms)
  (let ((saved-values (multiple-value-list ,form1)))
    ,@forms
    (values-list saved-value)))

The latter conses even if the form doesn't return multiple values.

PROGN doesn't have the same problem because it doesn't have to save
anything away.  It just returns the values of the last form, so it can just
copy them as soon as they're returned, or perhaps adjust the stack pointer
so that they're returned directly to the previous caller.

-- 
Barry Margolin, ··············@level3.com
Genuity Managed Services, a Level(3) Company, Woburn, MA
*** DON'T SEND TECHNICAL QUESTIONS DIRECTLY TO ME, post them to newsgroups.
Please DON'T copy followups to me -- I'll assume it wasn't posted to the group.
From: Peter Seibel
Subject: Re: Why multiple-value-prog1?
Date: 
Message-ID: <m3znls0xbm.fsf@javamonkey.com>
Barry Margolin <··············@level3.com> writes:

> In article <··············@javamonkey.com>,
> Peter Seibel  <·····@javamonkey.com> wrote:
> >I was wondering why MULTIPLE-VALUE-PROG1 existed--i.e. why doesn't
> >PROG1 just propogate multiple values the way PROGN does.
> 
> It simplifies the implementation if it knows how many values it has
> to save. The code generated for PROG1 just has to reserve a single
> register or stack location, rather than deal with arbitrary numbers
> of values (perhaps by consing a list). E.g. it can be:
> 
> (defmacro prog1 (form1 &rest forms)
>   (let ((saved-value ,form1))
>     ,@forms
>     saved-value))
> 
> (defmacro multiple-value-prog1 (form1 &rest forms)
>   (let ((saved-values (multiple-value-list ,form1)))
>     ,@forms
>     (values-list saved-value)))
> 
> The latter conses even if the form doesn't return multiple values.
> 
> PROGN doesn't have the same problem because it doesn't have to save
> anything away. It just returns the values of the last form, so it
> can just copy them as soon as they're returned, or perhaps adjust
> the stack pointer so that they're returned directly to the previous
> caller.

Ah. Makes sense. Thanks.

-Peter

-- 
Peter Seibel                                      ·····@javamonkey.com

  The intellectual level needed   for  system design is  in  general
  grossly  underestimated. I am  convinced  more than ever that this
  type of work is very difficult and that every effort to do it with
  other than the best people is doomed to either failure or moderate
  success at enormous expense. --Edsger Dijkstra
From: Nils Goesche
Subject: Re: Why multiple-value-prog1?
Date: 
Message-ID: <87fznj7li0.fsf@darkstar.cartan>
Barry Margolin <··············@level3.com> writes:

> In article <··············@javamonkey.com>,
> Peter Seibel  <·····@javamonkey.com> wrote:

> > I was wondering why MULTIPLE-VALUE-PROG1 existed--i.e. why
> > doesn't PROG1 just propogate multiple values the way PROGN
> > does.

> It simplifies the implementation if it knows how many values it
> has to save.  The code generated for PROG1 just has to reserve
> a single register or stack location, rather than deal with
> arbitrary numbers of values (perhaps by consing a list).

Yeah, that is certainly the reason, but frankly I have found this
point rather bizarre myself for quite some time.  Shouldn't the
compiler be able to tell the difference from the context easily
in any case?

Regards,
-- 
Nils G�sche
Ask not for whom the <CONTROL-G> tolls.

PGP key ID #xD26EF2A0
From: Kent M Pitman
Subject: Re: Why multiple-value-prog1?
Date: 
Message-ID: <sfwk7cv4r17.fsf@shell01.TheWorld.com>
Nils Goesche <···@cartan.de> writes:

> > has to save.  The code generated for PROG1 just has to reserve
> > a single register or stack location, rather than deal with
> > arbitrary numbers of values (perhaps by consing a list).
> 
> Yeah, that is certainly the reason, but frankly I have found this
> point rather bizarre myself for quite some time.  Shouldn't the
> compiler be able to tell the difference from the context easily
> in any case?

Only sometimes.  In the case of

 (defun foo ()
   (prog1 (bar) (baz)))

you can't tell.

In retrospect, it's surprising we didn't just make it multiple values
and say that anyone who wanted to do the old PROG1 thing should do

 (defun foo ()
   (prog1 (values (bar)) (baz)))

as an optimization.  This would have preserved the normal design rule
that we had for CL that programs should run nicely without declarations
and should run more optimally with declarations.

IMO, this is something we probably could have done better, but at the
same time it's in the noise, since it's not doing something
incomprehensible, unlearnable, or impossible to live with.
From: Nils Goesche
Subject: Re: Why multiple-value-prog1?
Date: 
Message-ID: <87bry77idx.fsf@darkstar.cartan>
Kent M Pitman <······@world.std.com> writes:

> IMO, this is something we probably could have done better, but
> at the same time it's in the noise, since it's not doing
> something incomprehensible, unlearnable, or impossible to live
> with.

Quite right.

Regards,
-- 
Nils G�sche
Ask not for whom the <CONTROL-G> tolls.

PGP key ID #xD26EF2A0
From: Tim Bradshaw
Subject: Re: Why multiple-value-prog1?
Date: 
Message-ID: <ey3k7cvisrm.fsf@cley.com>
* Nils Goesche wrote:

> Yeah, that is certainly the reason, but frankly I have found this
> point rather bizarre myself for quite some time.  Shouldn't the
> compiler be able to tell the difference from the context easily
> in any case?

No.  Only if it knows the number of return values of whatever it
calls.  To give an extreme case:

(defun foo (f g)
 (multiple-value-prog1 (funcall f) (funcall g)))

(I still would like PROG1 do do MV by default and for there to be a
single-value version, but that's because I strongly prefer clarity
over optimisability.)

--tim