From: chairam
Subject: multiple return values
Date: 
Message-ID: <hnvoc1ddk7vgannbc1ie2fi2u30nudo4if@4ax.com>
Hi, I'm studying lisp

Some function like:  truncate, floor, round,   return 2 values

if you want to catch all values you have to use multiple-value-bind
but:
why 2 values and not a list of 2 values?

I have my own opinion but appreciate others'

Bye Chairam

From: Geoffrey Summerhayes
Subject: Re: multiple return values
Date: 
Message-ID: <CC%ye.7450$Ud.892679@news20.bellglobal.com>
"chairam" <·······@despammed.com> wrote in message ·······································@4ax.com...
> Hi, I'm studying lisp
>
> Some function like:  truncate, floor, round,   return 2 values
>
> if you want to catch all values you have to use multiple-value-bind
> but:
> why 2 values and not a list of 2 values?
>
> I have my own opinion but appreciate others'
>

The second return value is not used in most cases, so the calling
code can just ignore it rather than having to call FIRST on the
return value to get the required result. AFAIK, it may even be
possible for a smart compiler to avoid calculating the second
value, etc. when it knows only the first will be used. Don't
know if any compiler does this though.

--
Geoff 
From: Matthias Buelow
Subject: Re: multiple return values
Date: 
Message-ID: <3j3gahFnuvo3U2@news.dfncis.de>
chairam <·······@despammed.com> wrote:

>Some function like:  truncate, floor, round,   return 2 values
>if you want to catch all values you have to use multiple-value-bind
>but:
>why 2 values and not a list of 2 values?
>I have my own opinion but appreciate others'

Multiple return values are an efficiency hack.

mkb.
From: Pietro Campesato
Subject: Re: multiple return values
Date: 
Message-ID: <1120702301.793447.35220@g43g2000cwa.googlegroups.com>
I've always had the feeling you should avoid returning multiple values
instead of a list: I guess the only exception would be functions like
the ones mentioned above or, perhaps, when you need to return a tree.
Does anyone agree (or disagree)?
From: Ulrich Hobelmann
Subject: Re: multiple return values
Date: 
Message-ID: <3j452kFo2i1uU1@individual.net>
Pietro Campesato wrote:
> I've always had the feeling you should avoid returning multiple values
> instead of a list: I guess the only exception would be functions like
> the ones mentioned above or, perhaps, when you need to return a tree.
> Does anyone agree (or disagree)?

Well, I think it's awkward (and unnecessary) to cons up a list, 
only to destruct it a moment later.  Same with creating a Tuple 
class in Java to be able to return multiple values (in C at least 
I have pointer args).

If you look at the ML languages, multiple values are just tuples 
that are probably left in machine registers.  So on one hand it is 
an efficiency hack, but OTOH it is just tuples.  Maybe we should 
use vectors and have the compiler decide when to store them in 
registers?  I think ML's typing makes this much easier ;)  So 
instead of multiple values there should be a declaration to tell 
the compiler how many values you return.  That way the efficiency 
hack is at the right place in the language.

-- 
By claiming a patent [...], I'm saying that you are not permitted 
to use your own knowledge to further your ends. By what right?
	Roderick T. Long
From: Matthias Buelow
Subject: Re: multiple return values
Date: 
Message-ID: <86slyqk69f.fsf@drjekyll.mkbuelow.net>
Ulrich Hobelmann <···········@web.de> writes:

>I think ML's typing makes this much easier ;)  So instead of multiple
>values there should be a declaration to tell the compiler how many
>values you return.  That way the efficiency hack is at the right place
>in the language.

Imho it's not the "Lisp way" to start declaring left and right.
Multiple return values work pretty well for this situation. The one
thing one could do is somehow teach the compiler to make list consing
of very small lists in a special way, invisible to the programmer, by
putting values in registers or something like that. But that would
probably complicate list/car/cdr/etc. beyond any efficiency benefit.
Then there's stilll the syntactic advantage in many situations where
you use just the first value (but I wouldn't really care having to
write (car ...) if I knew that the compiler could somehow "optimize
away" the car in that case.) I personally would like functions to
receive, and return exactly one value (a list, if multiple arguments).
That would be elegant but probably not all too practical.

mkb.
From: Pascal Costanza
Subject: Re: multiple return values
Date: 
Message-ID: <3j49sbFnv2njU1@individual.net>
Pietro Campesato wrote:
> I've always had the feeling you should avoid returning multiple values
> instead of a list: I guess the only exception would be functions like
> the ones mentioned above or, perhaps, when you need to return a tree.
> Does anyone agree (or disagree)?

I disagree. It's usually safe to return multiple values instead of a 
list. The caller can decide to turn this into a list later on, so there 
are no drawbacks.

The decision should be based on the semantics of the results you return. 
If the return value is a list by design (because it collects elements, 
so you use it like other collection types, like vector, hashtable, 
etc.), then return a list. If the return values are not inherently 
usefully combined into a list, use multiple values.


Pascal

-- 
2nd European Lisp and Scheme Workshop
July 26 - Glasgow, Scotland - co-located with ECOOP 2005
http://lisp-ecoop05.bknr.net/
From: Pietro Campesato
Subject: Re: multiple return values
Date: 
Message-ID: <1120846269.958142.70940@g43g2000cwa.googlegroups.com>
So are you saying that, in such cases, multiple values convey your
intent more clearly? (Definitely sounds sensible: I stand corrected.)
From: Coby Beck
Subject: Re: multiple return values
Date: 
Message-ID: <CCFze.143785$on1.122248@clgrps13>
"Pietro Campesato" <················@gmail.com> wrote in message 
····························@g43g2000cwa.googlegroups.com...
> So are you saying that, in such cases, multiple values convey your
> intent more clearly? (Definitely sounds sensible: I stand corrected.)

I think having the option of returning multiple values is great.  For me it 
just fits the bill perfectly for a certain class of circumstances, those 
times when you have done some expensive computation, either efficiency wise 
or brain cell wise and the main goal comes along with a potentially useful 
after thought.  Packing it in a list forces all callers to unpackage it even 
though it is highly unusual that the secondary value is interesting. 
Returning it as a secondary value is a way of not wasting the information 
you happen to have even though you might not know when it would be needed, 
its a just-in-case kind of thing.  And lo and behold, eventually it will be 
exactly what a particular call really needs.

It's kind of like sending a few yards of fabric to a seamstress asking for a 
set of curtains.  You get the curtains as the primary value and then the 
secondary return value is the leftover fabric.  Maybe you'll just throw it 
out, but it may be a very handy thing to have that you could not have easily 
got anywhere else.

-- 
Coby Beck
(remove #\Space "coby 101 @ bigpond . com")
From: Pascal Costanza
Subject: Re: multiple return values
Date: 
Message-ID: <3j49jhFnuub4U1@individual.net>
Matthias Buelow wrote:
> chairam <·······@despammed.com> wrote:
> 
>>Some function like:  truncate, floor, round,   return 2 values
>>if you want to catch all values you have to use multiple-value-bind
>>but:
>>why 2 values and not a list of 2 values?
>>I have my own opinion but appreciate others'
> 
> Multiple return values are an efficiency hack.

No, no, no. They are a convenience hack. It's really useful that you can 
ignore all but the first return value if you don't need the others. This 
happens quite often. It's also really useful that this allows you to 
evolve your functions to return more values than before without the need 
to change all the call sites but only those that actually need the 
additional return values.

The fact that they can be more efficient than lists is just a nice side 
effect.


Pascal

-- 
2nd European Lisp and Scheme Workshop
July 26 - Glasgow, Scotland - co-located with ECOOP 2005
http://lisp-ecoop05.bknr.net/
From: Matthias Buelow
Subject: Re: multiple return values
Date: 
Message-ID: <86oe9ek66m.fsf@drjekyll.mkbuelow.net>
Pascal Costanza <··@p-cos.net> writes:

>It's also really useful that this
>allows you to evolve your functions to return more values than before
>without the need to change all the call sites but only those that
>actually need the additional return values.

Hmm, I remember having argued against that before, that I consider
this to be a dangerous practice.

mkb.
From: Kent M Pitman
Subject: Re: multiple return values
Date: 
Message-ID: <u64vmy68f.fsf@nhplace.com>
Matthias Buelow <···@incubus.de> writes:

> Pascal Costanza <··@p-cos.net> writes:
> 
> >It's also really useful that this
> >allows you to evolve your functions to return more values than before
> >without the need to change all the call sites but only those that
> >actually need the additional return values.
> 
> Hmm, I remember having argued against that before, that I consider
> this to be a dangerous practice.

What is your metric of dangerous?

CL has had multiple values for decades.  Huge numbers of users don't
know they are there and are perfectly happy not using them.  Some users
know they are there and are perfectly happy using them.  That's a darned
good track record.

Imagined danger is not "danger in fact".

(Surely there's a cool latin word I could have used for this last quoted
 phrase.  Someone help me.)

But I'm serious--is it enough to just say something is dangerous because
you imagine a particular practice might lead to problems?  Like people say
it's dangerous to teach kids about condoms because it might cause them to
have sex, but the stats actually say that where condoms are not taught, 
there's not necessarily less sex and there's a lot more pregnancy?  By what
metric do we allow people to bandy about the term "dangerous", when there
are dangers to not doing a certain practice.

Just to complicate matters, I'll allege it's dangerous to call this practice
dangerous. :)  At least that emphasizes the two-sided nature of this.

- - - -

Not returning multiple values does not remove the programmer need for them.
It just means they get accomplished in different ways, such as returning 
structures (potential wasted consing) or side-effect of structures passed
as arguments or (not really offered by lisp) side-effect of variables passed
in call-by-reference style [effectively, Lisp uses the structure trick 
to work around this].  Multiple values are clearly an elegant solution to 
this.

Making every caller use the same values returned by a function is bad because
it means you have to either have multiple versions of the same function
(e.g, both a QUOTIENT and a QUOTIENT-AND-REMAINDER function) or else you
have to arrange for the caller to be prepared for and to discard the values.
e.g., instead of

 (defun floor3 (n) (floor n 3))

 (mapcar #'floor3 some-list)
 (mapcar #'floor3 some-other-list)
 ...

you have to write either:

 (defun floor3-multi (n) (floor n 3))

 (defun floor3-quotient-only (n)
   (nth-value 0 (floor n 3)))

 (defun floor3-remainder-only (n)
   (nth-value 1 (floor n 3)))

 (mapcar #'floor3-quotient-only some-list)
 (mapcar #'floor3-quotient-only some-other-list)
 ...

or else you have to write:

 (defun floor3 (n) (floor n 3))

 (mapcar #'(lambda (n) (nth-value 1 (floor3 n))) some-list)
 (mapcar #'(lambda (n) (nth-value 1 (floor3 n))) some-other-list)
 ...

And that's only if you believe that NTH-VALUE is even appropriate
in a world where you are doing strong testing.  I'm sure some purists,
emboldened by the elimination of unwanted discarding of "stray" return
values, would say people should write:

 (mapcar #'(lambda (n)
             (multiple-value-bind (q r)
                 (floor3 n)
               (declare (ignore r))
               q))
         some-list)

  (mapcar #'(lambda (n)
             (multiple-value-bind (q r)
                 (floor3 n)
               (declare (ignore r))
               q))
         some-other-list)

This is in some confused sense clearer but also really hard to read and
likely to have bugs just becuase it is so far from what the user wanted
to say that it's hard to pick out the "intended" parts from the "make-work"
parts that were added by language designers who think it's good for people
to have to declare stuff.

I regard any of those options as so substantially unattractive as to be
dangerous to any notion of elegant coding.

Further, as to the issue of extending the number of values, every time
you want to provide a new piece of information under the above scheme,
you multiply the number of places that have to be changed because you can't
even add an ignored value without having to do:

  (mapcar #'(lambda (n)
             (multiple-value-bind (q r z)
                 (floor3 n)
               (declare (ignore r z))
               q))
         some-other-list)

Now, is the program REALLY any "safer from bugs" if I add an unexplained 
extra ignored parameter?  You might say "sure, because it wasn't a parameter
that's getting used."  Well, what if I say "yeah, that was how I worked in
old CL when optional args could be added quietly. I always assumed people
might not know a new arg was there so I always relied on a prisoner's 
dilemma style solution to say that I'd better not change the contract 
too much since the user might not be reading my updated definition's doc.
BUT NOW that I know that people MUST re-read the doc to find out how many
args there are, I changed the function more radically. e.g., now it returns
NIL if n is negative and z is the value q would have been in that case.
I figured you'd know when your read the doc and were updating your code,
but you didn't really read the doc--you just updated your code based on a
new arg."

Now, you can say this serves the user right for not reading the doc. I've
heard documentation people say the same about their precious doc, too.
"Too bad if the guy erases his disk because he didn't read the full doc.
I can't be responsible for people just wanting to read the quickstart and
ignoring all that doc I wrote."  Yeah, you can say this.  But IMO that doesn't
make your doc good and the user wrong.  

And if you make a programming language that invites people to do certain kinds
of operations, you should think about what typical styles people want to 
work in.  CL users often are just working with interactive tools that show
them arglists.  IMO, it's safer for writers of code to know that added
extra args are intended to be ignorable and that interfaces had better 
change with that in mind than it is for writers of code to be assumed to
carefully read the doc and meticulously code to spec.  That's a possible
theory of language design, but it's solidly covered in the static languages
camp and it doesn't help Lisp.

Lisp can already have block compilers that want to do so look at the
numbers of return values and issue warnings for things that are
statically detectable.  I'll be the Python compiler sometimes gives
interesting warnings in this regard, since my understanding is that it
does more with block compilation than most implementations.  But
that's still different than requiring users who don't want such
detection to twist their programs around to accomodate it just because
some individual says it's dangerous.

Add to the list of dangerous things: It's dangerous for all languages
to have the same restrictive theory of dangerous.  It's good for
people who want to escape languages that make you ultra-declare stuff
to have a place to go.  CL is that place.  It's fine for people who
want to make lots of logical claims and statically checked assertions
about their code at every step, too.  I think CL is not that place,
unless it's an optional extension that I can choose to use or not.

Just my opinion.
From: Matthias Buelow
Subject: Re: multiple return values
Date: 
Message-ID: <86ll4iiopd.fsf@drjekyll.mkbuelow.net>
Kent M Pitman <······@nhplace.com> writes:

>CL has had multiple values for decades.  Huge numbers of users don't
>know they are there and are perfectly happy not using them.  Some users
>know they are there and are perfectly happy using them.  That's a darned
>good track record.

I don't say that MRVs are dangerous, but Pascal's proposed development
approach of developing functions which change the number of return
values over time, without having to update all the call sites. MRVs
are useful for the originally mentioned arithmetic functions (where
the number of returned values is unlikely to change) and similar
"stable" interfaces.

mkb.
From: Kent M Pitman
Subject: Re: multiple return values
Date: 
Message-ID: <uhdf6v9sq.fsf@nhplace.com>
Matthias Buelow <···@incubus.de> writes:

> Kent M Pitman <······@nhplace.com> writes:
> 
> >CL has had multiple values for decades.  Huge numbers of users don't
> >know they are there and are perfectly happy not using them.  Some users
> >know they are there and are perfectly happy using them.  That's a darned
> >good track record.
> 
> I don't say that MRVs are dangerous, but Pascal's proposed development
> approach of developing functions which change the number of return
> values over time, without having to update all the call sites. MRVs
> are useful for the originally mentioned arithmetic functions (where
> the number of returned values is unlikely to change) and similar
> "stable" interfaces.

But that practice of adding additional return values upward compatibly
has been a common way for code to evolve, and is also time-tested.
I've just not seen it to cause problems.  So how is it different other
than that someone says so?

Are you also of the opinion that adding &OPTIONAL, &REST, or &KEY 
arguments to a function that was formerly of fixed or lesser arity
is bad unless you are forced to go update all the call sites?  That is
likewise used as a way of evolving code interfaces compatibly.
I've not heard that to lead to harm either.   If it's "dangerous",
you need to say way.  If it's not "dangerous", you need to say why it's
fundamentally different thna the situation of returning values.
From: Matthias Buelow
Subject: Re: multiple return values
Date: 
Message-ID: <86ekaaiftn.fsf@drjekyll.mkbuelow.net>
Kent M Pitman <······@nhplace.com> writes:

>But that practice of adding additional return values upward compatibly
>has been a common way for code to evolve, and is also time-tested.
>I've just not seen it to cause problems.  So how is it different other
>than that someone says so?

I'm not sure that that "evolving" of functions is such a good thing at
all, when it involves changing a function's "signature"; imho it's
much better to put new features into seperate, cleanly designed
functions instead of upholstering existing ones...

>Are you also of the opinion that adding &OPTIONAL, &REST, or &KEY 
>arguments to a function that was formerly of fixed or lesser arity
>is bad unless you are forced to go update all the call sites?  That is

Yes, I would think so. Of course, exceptions exist but I'd prefer them
to be very rare.

mkb.
From: Joe Marshall
Subject: Re: multiple return values
Date: 
Message-ID: <d5pujig0.fsf@comcast.net>
Matthias Buelow <···@incubus.de> writes:

> Kent M Pitman <······@nhplace.com> writes:
>
>>But that practice of adding additional return values upward compatibly
>>has been a common way for code to evolve, and is also time-tested.
>>I've just not seen it to cause problems.  So how is it different other
>>than that someone says so?
>
> I'm not sure that that "evolving" of functions is such a good thing at
> all, when it involves changing a function's "signature"; imho it's
> much better to put new features into seperate, cleanly designed
> functions instead of upholstering existing ones...

That's a nice theory, but not one I've seen in practice in the real
world.


-- 
~jrm
From: GP lisper
Subject: Re: multiple return values
Date: 
Message-ID: <1120864661.701d13d00f67fd68d6826613982e4e8f@teranews>
On Thu, 07 Jul 2005 19:38:07 -0400, <·············@comcast.net> wrote:
>
> Matthias Buelow <···@incubus.de> writes:
>
>> Kent M Pitman <······@nhplace.com> writes:
>>
>>>But that practice of adding additional return values upward compatibly
>>>has been a common way for code to evolve, and is also time-tested.
>>>I've just not seen it to cause problems.  So how is it different other
>>>than that someone says so?
>>
>> I'm not sure that that "evolving" of functions is such a good thing at
>> all, when it involves changing a function's "signature"; imho it's
>> much better to put new features into seperate, cleanly designed
>> functions instead of upholstering existing ones...
>
> That's a nice theory, but not one I've seen in practice in the real
> world.

I do it in order to leave "bread crumbs" behind, they allow some
checking when things go crazy, or serve as a basis for another avenue
of exploration.  Of course, after duping the function, renaming it
[sometimes renaming the old version instead] slightly, I upholster it
(no way would I consider a blank page restart) which can include
cleaning up bits here and there.  It's probably a function of
experience in a particular problem domain as to when a bread crumb is
left behind.  Perhaps Matthias means this style and not the 'start
over' style his post seems to imply.

See Kenny's CELLS for some examples of 'bread crumbs'.


-- 
LOOP :: a Domain Specific Language.
From: Joe Marshall
Subject: Re: multiple return values
Date: 
Message-ID: <irzjhj2f.fsf@comcast.net>
GP lisper <········@CloudDancer.com> writes:

> On Thu, 07 Jul 2005 19:38:07 -0400, <·············@comcast.net> wrote:
>>
>> Matthias Buelow <···@incubus.de> writes:
>>
>>> Kent M Pitman <······@nhplace.com> writes:
>>>
>>>>But that practice of adding additional return values upward compatibly
>>>>has been a common way for code to evolve, and is also time-tested.
>>>>I've just not seen it to cause problems.  So how is it different other
>>>>than that someone says so?
>>>
>>> I'm not sure that that "evolving" of functions is such a good thing at
>>> all, when it involves changing a function's "signature"; imho it's
>>> much better to put new features into seperate, cleanly designed
>>> functions instead of upholstering existing ones...
>>
>> That's a nice theory, but not one I've seen in practice in the real
>> world.
>
> I do it in order to leave "bread crumbs" behind, they allow some
> checking when things go crazy, or serve as a basis for another avenue
> of exploration.  Of course, after duping the function, renaming it
> [sometimes renaming the old version instead] slightly, I upholster it
> (no way would I consider a blank page restart) which can include
> cleaning up bits here and there.  

`bread crumbs' are ok, but the problem of duping the function is that
you now have two versions to maintain.

-- 
~jrm
From: GP lisper
Subject: Re: multiple return values
Date: 
Message-ID: <1120979702.a3cb7b22acae03413065df3e7891e9e7@teranews>
On Sat, 09 Jul 2005 15:32:08 -0400, <·············@comcast.net> wrote:
>
> GP lisper <········@CloudDancer.com> writes:
>>
>> I do it in order to leave "bread crumbs" behind, they allow some
>> checking when things go crazy, or serve as a basis for another avenue
>> of exploration.  Of course, after duping the function, renaming it
>> [sometimes renaming the old version instead] slightly, I upholster it
>> (no way would I consider a blank page restart) which can include
>> cleaning up bits here and there.  
>
> `bread crumbs' are ok, but the problem of duping the function is that
> you now have two versions to maintain.

Nope, I abandon the 'older' function (it was working at some level
after all) unless one of the mentioned conditions occurs, or I do
deadwood cleaning near project end.  Just the other day, I needed to
test how something was working by employing the 'first generation'
answer to see if the 'fourth' should be working.  This style evolved
over the years, and it works best in Lisp.


-- 
LOOP :: a Domain Specific Language.
From: Joe Marshall
Subject: Re: multiple return values
Date: 
Message-ID: <7jfyhdk3.fsf@comcast.net>
GP lisper <········@CloudDancer.com> writes:

> On Sat, 09 Jul 2005 15:32:08 -0400, <·············@comcast.net> wrote:
>>
>> GP lisper <········@CloudDancer.com> writes:
>>>
>>> I do it in order to leave "bread crumbs" behind, they allow some
>>> checking when things go crazy, or serve as a basis for another avenue
>>> of exploration.  Of course, after duping the function, renaming it
>>> [sometimes renaming the old version instead] slightly, I upholster it
>>> (no way would I consider a blank page restart) which can include
>>> cleaning up bits here and there.  
>>
>> `bread crumbs' are ok, but the problem of duping the function is that
>> you now have two versions to maintain.
>
> Nope, I abandon the 'older' function (it was working at some level
> after all) unless one of the mentioned conditions occurs, or I do
> deadwood cleaning near project end.  

I guess I don't understand how writing a new function (presumably with
a new signature) and abandoning the older one differs from `changing
the function's signature'.



-- 
~jrm
From: Kent M Pitman
Subject: Re: multiple return values
Date: 
Message-ID: <umzor8qp9.fsf@nhplace.com>
GP lisper <········@CloudDancer.com> writes:

> On Sat, 09 Jul 2005 15:32:08 -0400, <·············@comcast.net> wrote:
> >
> > GP lisper <········@CloudDancer.com> writes:
> >>
> >> I do it in order to leave "bread crumbs" behind, they allow some
> >> checking when things go crazy, or serve as a basis for another avenue
> >> of exploration.  Of course, after duping the function, renaming it
> >> [sometimes renaming the old version instead] slightly, I upholster it
> >> (no way would I consider a blank page restart) which can include
> >> cleaning up bits here and there.  
> >
> > `bread crumbs' are ok, but the problem of duping the function is that
> > you now have two versions to maintain.
> 
> Nope, I abandon the 'older' function (it was working at some level
> after all) unless one of the mentioned conditions occurs, or I do
> deadwood cleaning near project end.

You're assuming youre in control of all code using your function.

When I talked about evolving, I was talking about an entire
interconnected community sharing code and upgrading gradually,
compatibly without synchronization points that require everyone to
switch over all of a sudden or even necessarily "soon".
From: Pascal Costanza
Subject: Re: multiple return values
Date: 
Message-ID: <3j5fukFoatg8U1@individual.net>
Matthias Buelow wrote:

> Kent M Pitman <······@nhplace.com> writes:
> 
>>But that practice of adding additional return values upward compatibly
>>has been a common way for code to evolve, and is also time-tested.
>>I've just not seen it to cause problems.  So how is it different other
>>than that someone says so?
> 
> I'm not sure that that "evolving" of functions is such a good thing at
> all, when it involves changing a function's "signature"; imho it's
> much better to put new features into seperate, cleanly designed
> functions instead of upholstering existing ones...

Again, multiple return values are good when all of them are generated by 
the same algorithm anyway. Evolving a function towards returning more 
values is a good idea when you realize that some of the values are 
needed by the call site, what you may not have realized in the 
beginning. Creating new independent functions for such cases probably 
means that you  duplicate code. I agree with you in cases where you 
would randomly combine different code into the same function just to 
produce multiple values - if these code fragments are independent, they 
should belong in different functions.

It's still hard to understand what you mean by dangerous. For example, 
programs are not known to crash because of multiple values. So what 
kinds of dangers do you actually have in mind?

>>Are you also of the opinion that adding &OPTIONAL, &REST, or &KEY 
>>arguments to a function that was formerly of fixed or lesser arity
>>is bad unless you are forced to go update all the call sites?  That is
> 
> Yes, I would think so. Of course, exceptions exist but I'd prefer them
> to be very rare.

Note that you can design your functions upfront with extensibility in 
mind. When you are not sure yet what degree of parameterization you need 
for a particular function, you can start with very little parameters, 
but support keyword arguments from the start. This allows you to add 
more keyword arguments later on as soon as you need them. The fact that 
you use those lambda list keywords doesn't have to be an afterthought, 
only the particular parameters that you add later on.

For example, the CLOS MOP is a very nice design in this regard. It draws 
some of its power from the fact that you can add keyword parameters in 
your own more specialized methods. The left-to-right precedence rule for 
keyword parameters is also very useful here. The general idiom is this:

(defmethod do-something
   ((object my-more-specialized-class)
    &rest args
    &key my-new-keyword1 my-new-keyword2
    some-old-keyword1 some-old-keyword2
    &allow-other-keys) ; <- deal with other keywords implicitly
   (declare (dynamic-extent args)) ; <- for efficiency
   (process-your-own-keywords ...)
   (apply #'call-next-method ; "super" call
          object
          :some-old-keyword1 ; overrides bindings
          some-new-value     ; for some-old-keyword1
          args))             ; that are still left in args

I think this is a very elegant solution and not at all a bad idea.

(The most frequent error I make when I use that idiom is that I forget 
to pass the first parameter to call-next-method, "object" in this 
example. So maybe positional arguments are more "dangerous" than keyword 
argument... ;)


Pascal

-- 
2nd European Lisp and Scheme Workshop
July 26 - Glasgow, Scotland - co-located with ECOOP 2005
http://lisp-ecoop05.bknr.net/
From: Bulent Murtezaoglu
Subject: Re: multiple return values
Date: 
Message-ID: <87slyqvbfe.fsf@p4.internal>
>>>>> "MB" == Matthias Buelow <···@incubus.de> writes:
[...]
    MB> I don't say that MRVs are dangerous, but Pascal's proposed
    MB> development approach of developing functions which change the
    MB> number of return values over time, without having to update
    MB> all the call sites. 

Hmm.  I don't agree.  What Pascal suggests yields results that are 
indistinguishable from planning to return multiple values from the 
outset.  No?  I would agree with you if this were about &optionals in 
lambda lists abused this way, but for multiple-values it seems sane 
safe and efficient.

cheers,

BM
From: Kent M Pitman
Subject: Re: multiple return values
Date: 
Message-ID: <ud5puv9rc.fsf@nhplace.com>
Bulent Murtezaoglu <··@acm.org> writes:

> >>>>> "MB" == Matthias Buelow <···@incubus.de> writes:
> [...]
>     MB> I don't say that MRVs are dangerous, but Pascal's proposed
>     MB> development approach of developing functions which change the
>     MB> number of return values over time, without having to update
>     MB> all the call sites. 
> 
> Hmm.  I don't agree.  What Pascal suggests yields results that are 
> indistinguishable from planning to return multiple values from the 
> outset.  No?  I would agree with you if this were about &optionals in 
> lambda lists abused this way, but for multiple-values it seems sane 
> safe and efficient.

Can you articulate what you worry about in the case of &optionals?
From: Pascal Costanza
Subject: Re: multiple return values
Date: 
Message-ID: <3j561dFo0soaU1@individual.net>
Kent M Pitman wrote:
> Bulent Murtezaoglu <··@acm.org> writes:
> 
>>>>>>>"MB" == Matthias Buelow <···@incubus.de> writes:
>>
>>[...]
>>    MB> I don't say that MRVs are dangerous, but Pascal's proposed
>>    MB> development approach of developing functions which change the
>>    MB> number of return values over time, without having to update
>>    MB> all the call sites. 
>>
>>Hmm.  I don't agree.  What Pascal suggests yields results that are 
>>indistinguishable from planning to return multiple values from the 
>>outset.  No?  I would agree with you if this were about &optionals in 
>>lambda lists abused this way, but for multiple-values it seems sane 
>>safe and efficient.
> 
> Can you articulate what you worry about in the case of &optionals?

I generally prefer keyword arguments over optionals. a) Optionals 
require you to evaluate arguments in an order that I as a caller might 
not agree with. b) When I want to pass a value to one of the later 
optionals I have to provide values for all the ones that precede it.

a) can be worked around by binding the values to temporary variables, b) 
  cannot be worked around as far as I can see. Keyword arguments avoid 
both problems.

Multiple return values have similar problems with the order of values 
returned. It would be nice if there were a way to get return values by 
keyword as well. Something like:

(key-value-bind
     (b d) ;; picks out :b and :d from the list of return values
     (some-function ...)
   ...)

and likewise on the return site:

(key-values
   :a 1 :b 2 :c 3 :d 4)


Hm, should be straightforward to implement, but haven't really checked.


Pascal

-- 
2nd European Lisp and Scheme Workshop
July 26 - Glasgow, Scotland - co-located with ECOOP 2005
http://lisp-ecoop05.bknr.net/
From: William Bland
Subject: Re: multiple return values
Date: 
Message-ID: <pan.2005.07.07.17.37.57.33963@abstractnonsense.com>
On Thu, 07 Jul 2005 19:11:08 +0200, Pascal Costanza wrote:
> 
> It would be nice if there were a way to get return values by 
> keyword as well. Something like:
> 
> (key-value-bind
>      (b d) ;; picks out :b and :d from the list of return values
>      (some-function ...)
>    ...)
> 
> and likewise on the return site:
> 
> (key-values
>    :a 1 :b 2 :c 3 :d 4)
> 
> 
> Hm, should be straightforward to implement, but haven't really checked.
> 

Yup, I've also thought that would be a nice feature.  I often prefer
things that use keywords rather than relying on positions - it can make
code clearer.  I would suggest though, that there should be some way to
specify a given key as the primary, so that client code can pick out just
that value without having to use KEY-VALUE-BIND.  For example:

(defun search-string-for-chars (string chars)
  (let* ((index (position-if (lambda (char) (member char chars)) string))
	 (char (if index (aref string index))))
    (key-values :primary :index index
                :char char)))

That way, if I care about both, I can do

(key-value-bind (:index i :char c) (search-string-for-chars ...)
  (format t "Found ~A at position ~A~%" c i))

But if I only care about the position of the first char found, I can still
just do

(format t "Found one at position ~A~%" (search-string-for-chars ...))

Do you think that would make the implementation much harder?

Best wishes,
		Bill.
From: Pascal Costanza
Subject: Re: multiple return values
Date: 
Message-ID: <3j58h1Fngvt0U1@individual.net>
William Bland wrote:
> On Thu, 07 Jul 2005 19:11:08 +0200, Pascal Costanza wrote:
> 
>>It would be nice if there were a way to get return values by 
>>keyword as well. Something like:
>>
>>(key-value-bind
>>     (b d) ;; picks out :b and :d from the list of return values
>>     (some-function ...)
>>   ...)
>>
>>and likewise on the return site:
>>
>>(key-values
>>   :a 1 :b 2 :c 3 :d 4)
>>
>>
>>Hm, should be straightforward to implement, but haven't really checked.
> 
> Yup, I've also thought that would be a nice feature.  I often prefer
> things that use keywords rather than relying on positions - it can make
> code clearer.  I would suggest though, that there should be some way to
> specify a given key as the primary, so that client code can pick out just
> that value without having to use KEY-VALUE-BIND.  For example:
> 
> (defun search-string-for-chars (string chars)
>   (let* ((index (position-if (lambda (char) (member char chars)) string))
> 	 (char (if index (aref string index))))
>     (key-values :primary :index index
>                 :char char)))
> 
> That way, if I care about both, I can do
> 
> (key-value-bind (:index i :char c) (search-string-for-chars ...)
>   (format t "Found ~A at position ~A~%" c i))
> 
> But if I only care about the position of the first char found, I can still
> just do
> 
> (format t "Found one at position ~A~%" (search-string-for-chars ...))
> 
> Do you think that would make the implementation much harder?

Would it be sufficient if you could return the primary without any keyword?

? (destructuring-value-bind
     (primary &key b d &allow-other-keys)
     (values 1 :a 2 :b 3 :c 4 :d 5)
     (print primary)
     (print b)
     (print d))

1
3
5


BTW, much simpler version:

(defmacro destructuring-value-bind ((&rest args) values-form &body body)
   `(multiple-value-call
     (lambda (,@args) ,@body)
     ,values-form))

Maybe the name is not quite correct anymore. What about lambda-value-bind?

Pascal

-- 
2nd European Lisp and Scheme Workshop
July 26 - Glasgow, Scotland - co-located with ECOOP 2005
http://lisp-ecoop05.bknr.net/
From: William Bland
Subject: Re: multiple return values
Date: 
Message-ID: <pan.2005.07.07.18.29.45.72455@abstractnonsense.com>
On Thu, 07 Jul 2005 19:53:37 +0200, Pascal Costanza wrote:
> 
> Would it be sufficient if you could return the primary without any keyword?
> 
> ? (destructuring-value-bind
>      (primary &key b d &allow-other-keys)
>      (values 1 :a 2 :b 3 :c 4 :d 5)
>      (print primary)
>      (print b)
>      (print d))
> 
> 1
> 3
> 5
> 

Yup, I think that does the job.

> BTW, much simpler version:
> 
> (defmacro destructuring-value-bind ((&rest args) values-form &body body)
>    `(multiple-value-call
>      (lambda (,@args) ,@body)
>      ,values-form))

Nice :-)

Cheers,
	Bill.
From: Pascal Costanza
Subject: Re: multiple return values
Date: 
Message-ID: <3j57eoFo644tU1@individual.net>
Pascal Costanza wrote:

> Multiple return values have similar problems with the order of values 
> returned. It would be nice if there were a way to get return values by 
> keyword as well. Something like:
> 
> (key-value-bind
>     (b d) ;; picks out :b and :d from the list of return values
>     (some-function ...)
>   ...)
> 
> and likewise on the return site:
> 
> (key-values
>   :a 1 :b 2 :c 3 :d 4)
> 
> Hm, should be straightforward to implement, but haven't really checked.

Yep:

(defmacro destructuring-value-bind ((&rest args) values-form &body body)
   (let ((values (gensym)))
     `(multiple-value-call
       (lambda (&rest ,values)
         (declare (dynamic-extent ,values))
         (destructuring-bind
           (,@args)
           ,values
           ,@body))
       ,values-form)))

? (destructuring-value-bind
      (&key b d &allow-other-keys)
      (values :a 1 :b 2 :c 3 :d 4)
      (print b)
      (print d))

2
4

;-)


Pascal

-- 
2nd European Lisp and Scheme Workshop
July 26 - Glasgow, Scotland - co-located with ECOOP 2005
http://lisp-ecoop05.bknr.net/
From: Bulent Murtezaoglu
Subject: Re: multiple return values
Date: 
Message-ID: <87oe9ev5p5.fsf@p4.internal>
>>>>> "KMP" == Kent M Pitman <Kent> writes:
[...]
    >> Hmm.  I don't agree.  What Pascal suggests yields results that
    >> are indistinguishable from planning to return multiple values
    >> from the outset.  No?  I would agree with you if this were
    >> about &optionals in lambda lists abused this way, but for
    >> multiple-values it seems sane safe and efficient.

    KMP> Can you articulate what you worry about in the case of
    KMP> &optionals?

Sure, I think I sometimes abuse them when I rush.  Mainly what I
dislike about sticking afterthoughts in optionals is that I often use
the default nil or use supplied-p to decide to run the original code
and write a new function body for the case where the optional is
supplied.  That is, the &optional is not really optional when the
function itself ought to have had a required parameter and thus should
have been a different function.  (otherwise optionals are fine, of
course) 

That is, (defun foo (p1 p2) (blah p1 p2)) is good enough
initially but now I realize (defun foo (p1 p2 p3) ...) is far more
appropriate for foo, and indeed essential at the present call site.
P3 is perfectly reasonable and useful to pass at the original call
sites too (perhaps it helps with performance? accuracy? places an 
icon more appropriately? whatever) but I am lazy and I now end up 
doing:

(defun foo (p1 p2 &optional p3)
  (cond (p3 (the-blah-I-should-have-written p1 p2 p3)) 
        (t (blah p1 p2))))      

perhaps sometimes less egregiously 

(defun foo (p1 p2 &optional (p3 the-default-that-happens-to-work-sometimes))
  (the-blah-I-should-have-written p1 p2 p3))

In the multiple value case Pascal mentioned, I start with something 
like:

(defun bar (q1 q2)
  (let ((x (something-complicated-with q1)))     
     ; ...
     (something-else x q2)))

and then eventually I realize that at the _present_ call site x would 
be handy and simply modify bar:

(defun bar (q1 q2)
  (let ((x (something-complicated-with q1)))
     ; ...     
     (values (something-else x q2) x)))

nothing is unduly disturbed, and everything is fine at the original 
call sites.  My function computed x anyway, the original call 
sites did not need it, but the present one does.  I would probably 
have written it this way the first time had I known about the 
computation at the latest call site. 

Now, I realize I picked two extremes, but I couldn't think up a bad 
usage example with multiple values analogous to the &optional case 
above.  Is there one?  There doesn't seem to be a symmetry here.

cheers,

BM 
 
From: Pascal Costanza
Subject: Re: multiple return values
Date: 
Message-ID: <3j501tFof1oqU1@individual.net>
Matthias Buelow wrote:
> Pascal Costanza <··@p-cos.net> writes:
> 
>>It's also really useful that this
>>allows you to evolve your functions to return more values than before
>>without the need to change all the call sites but only those that
>>actually need the additional return values.
> 
> Hmm, I remember having argued against that before, that I consider
> this to be a dangerous practice.

Yeah, that's right, life is dangerous... ;)


Pascal

P.S.: There was recently a discussion in comp.lang.scheme about multiple 
return values, maybe it was over there where you have made that statement?

-- 
2nd European Lisp and Scheme Workshop
July 26 - Glasgow, Scotland - co-located with ECOOP 2005
http://lisp-ecoop05.bknr.net/
From: Christopher C. Stacy
Subject: Re: multiple return values
Date: 
Message-ID: <ufyurz3l8.fsf@news.dtpq.com>
chairam <·······@despammed.com> writes:
> Some function like:  truncate, floor, round,   return 2 values
> if you want to catch all values you have to use multiple-value-bind
> but: why 2 values and not a list of 2 values?

Not putting the values into a list allows you to
immediately use the first return value without
having to pick apart any intermediate list structure.

  (defun foo (x) ...)             ;; Only takes one arg.
  (defun bar () (values 1 2 3))   ;; Returns 3 values.

  (foo (bar))

If you really want the values packaged up as a list.
use the function VALUES-LIST.
From: Kent M Pitman
Subject: Re: multiple return values
Date: 
Message-ID: <ull4jchpt.fsf@nhplace.com>
······@news.dtpq.com (Christopher C. Stacy) writes:

> chairam <·······@despammed.com> writes:
> > Some function like:  truncate, floor, round,   return 2 values
> > if you want to catch all values you have to use multiple-value-bind
> > but: why 2 values and not a list of 2 values?

I don't recommend getting them this way, btw.  It conses and if all you're
going to do is pass it to something else, I'd recommend MULTIPLE-VALUE-BIND.
(See below.)

> Not putting the values into a list allows you to
> immediately use the first return value without
> having to pick apart any intermediate list structure.
> 
>   (defun foo (x) ...)             ;; Only takes one arg.
>   (defun bar () (values 1 2 3))   ;; Returns 3 values.
> 
>   (foo (bar))
> 
> If you really want the values packaged up as a list.
> use the function VALUES-LIST.

I agree with what Chris said.  In addition:

While it's normal (read: not a bug) to use multiple values,
it's not as common (statistically).  Consequently, it helps draw
attention to the unusual (though not abnormal) situation of using
both values, just as it's often useful to name other intermediate 
values using LET variables. e.g.,

 (multiple-value-bind (q r)
     (floor 5 3)
   (foo q r))

Btw, if you plan to use only one particular value, you may find
NTH-VALUE to be of use.  It's zero-indexed, so the first value is 0,
second is 1, etc. (just the same as for NTH).  e.g.:

 (foo (nth-value 1 (floor 5 3))) ;pass FOO the remainder from FLOOR
From: Luke Crook
Subject: Re: multiple return values
Date: 
Message-ID: <1120721016.506554.200530@z14g2000cwz.googlegroups.com>
Kent M Pitman wrote:
>
> While it's normal (read: not a bug) to use multiple values,
> it's not as common (statistically).  Consequently, it helps draw
> attention to the unusual (though not abnormal) situation of using
> both values, just as it's often useful to name other intermediate
> values using LET variables. e.g.,

Is this the reason why multiple values returned by VALUES cannot be
used directly in a function call? For example:

(take-two-values (return-two-values))
From: Kent M Pitman
Subject: Re: multiple return values
Date: 
Message-ID: <ubr5fxapl.fsf@nhplace.com>
"Luke Crook" <····@balooga.com> writes:

> Kent M Pitman wrote:
> >
> > While it's normal (read: not a bug) to use multiple values,
> > it's not as common (statistically).  Consequently, it helps draw
> > attention to the unusual (though not abnormal) situation of using
> > both values, just as it's often useful to name other intermediate
> > values using LET variables. e.g.,
> 
> Is this the reason why multiple values returned by VALUES cannot be
> used directly in a function call? For example:
> 
> (take-two-values (return-two-values))

If I understand your question right, the short answer is probably yes.
But I'm not sure what the 'this' you're referring to is, and probably
a longer answer will help assure I don't confuse you.  The following 
is an approximate description of the motivations for some of this:

Ordinarily, in normal function calling, only the primary value of each
argument evaluation is used.  This allows functions to return "extra
sometimes-useful information" in a discardable way.  For example:

 (setq my-table (make-hash-table))
 (gethash 'foo my-table) => NIL, NIL

The first NIL is the default default value and the second return value is
telling you that the thing wasn't in the table.  Contrast this with:

 (gethash 'foo my-table 7) => 7, NIL

where 7 is the specified default (as opposed to default default) and NIL
is telling you it still isn't in the table.

 (setf (gethash 'foo my-table) 8) puts 8 in the table for key FOO

so then

 (gethash 'foo my-table 8) => 8, T

meaning not only it's returning 8 but that the 8 was really in the table
and not a result of passing a specified default.  Consider that

 (gethash 'foo my-table 7) => 8, T

But normally, the whole point of supplying a default is that you don't care
if it was there or not, you know what you want.  So

 (+ (gethash 'foo my-table 7) 1) => 9

This is because the T is "extra" info and only the primary return value is
given to +.

If you REALLY wanted all the return values to go, you could do

 (apply #'+ (multiple-value-list (values 1 2 3))) => 6

but the other thing you can do is

 (multiple-value-call #'+ (floor 37 4)) => 10

since (floor 37 4) => 9, 1 and multiple-value-call picks up ALL the
return values.  USUALLY, though, you're still best off still capturing 
the return values explicitly by name as in

 (multiple-value-bind (q r)
     (floor 37 4)
   (+ q r))

since people sometimes extend functions to return "helpful" additional
values figuring that consumers are mostly doing normal calls and will
just discard such info.  MULTIPLE-VALUE-BIND, unlike DESTRUCTURING-BIND
and various lambda lists, doesn't mind if the list to bind to is short. e.g.,
if a 3rd value came back from FLOOR, the above form would still work.
From: Kirk Job Sluder
Subject: Re: multiple return values
Date: 
Message-ID: <87mzoyy3rm.fsf@debian.kirkjobsluder.is-a-geek.net>
Kent M Pitman <······@nhplace.com> writes:

> Ordinarily, in normal function calling, only the primary value of each
> argument evaluation is used.  This allows functions to return "extra
> sometimes-useful information" in a discardable way.  For example:
> 
>  (setq my-table (make-hash-table))
>  (gethash 'foo my-table) => NIL, NIL
> 
> The first NIL is the default default value and the second return value is
> telling you that the thing wasn't in the table.  Contrast this with:
> 
>  (gethash 'foo my-table 7) => 7, NIL

In full agreement here.  I just want to add another few reasons for
returning multiple values.  First, the primary return value can can also
be a list or other complex data structure.  Second, the multiple values
frequently have different semantic meaning, such as value + status
(gethash) or value + remainder (floor).  You may want a search function
to return a text match, and the location in the string of the match.  I
suppose that you can also use it to pass back state in your testing
code, that can be discarded in practice.

Flat lists can be used as a poor-man's structure, but it can lead to
problems if you try to iterate over a list of apples and oranges with no
clue other than position as to which is which.

-- 
Kirk Job-Sluder
"The square-jawed homunculi of Tommy Hilfinger ads make every day an
existential holocaust."  --Scary Go Round
From: Paul Dietz
Subject: Re: multiple return values
Date: 
Message-ID: <dajg15$9se$1@avnika.corp.mot.com>
Luke Crook wrote:

> Is this the reason why multiple values returned by VALUES cannot be
> used directly in a function call? For example:
> 
> (take-two-values (return-two-values))

Others have pointed out MULTIPLE-VALUE-CALL.

The big downside to what you've written there is the widespread
performance impact.  Every function call (that had a function call
as an argument form) would have to check how many values are
being returned by each subform, and dynamically collect those values
into its arguments.  This is contrast to the standard semantics,
where you can figure out statically the number of arguments.

There's a paper around somewhere that goes into this in more
detail.  Your idea is a common one that was deliberately rejected.

	Paul
From: Geoffrey Summerhayes
Subject: Re: multiple return values
Date: 
Message-ID: <6_dze.8580$Ud.1059090@news20.bellglobal.com>
"Paul Dietz" <············@motorola.com> wrote in message 
·················@avnika.corp.mot.com...
> Luke Crook wrote:
>
>> Is this the reason why multiple values returned by VALUES cannot be
>> used directly in a function call? For example:
>>
>> (take-two-values (return-two-values))
>
> Others have pointed out MULTIPLE-VALUE-CALL.
>
> The big downside to what you've written there is the widespread
> performance impact.  Every function call (that had a function call
> as an argument form) would have to check how many values are
> being returned by each subform, and dynamically collect those values
> into its arguments.  This is contrast to the standard semantics,
> where you can figure out statically the number of arguments.
>
> There's a paper around somewhere that goes into this in more
> detail.  Your idea is a common one that was deliberately rejected.
>

Kind of wish it was available though, I ended up writing this *half-baked* 
code:

(defun parse-lambda-list (list)
  (let (binders mv-lists quick args setfs optional-section (accept-mv t))
    (do ((x list (rest x)))
        ((null x) (values (nreverse binders) (nreverse mv-lists)
                          (nreverse quick) (nreverse args)))
      (if (eq '&mv (first x))
          (progn
            (unless accept-mv
              (error "Error &mv not allowed at this spot: ~S" list))
            (when optional-section
              (error "Error &mv not currently supported in &optional: ~S" 
list))
            (let ((g (gensym)))
              (unless (listp (second x))
                (error "Error argument for &mv not a list: ~S in ~S"
                       (second x) list))
              (push (second x) binders)
              (push g mv-lists)
              (push t quick)
              (push g args)
              ;(when optional-section
               ; (push (generate-setf g (second x)) setfs))
              (setf x (rest x)))) ; skip what directly follows &mv
        (progn
          (if (member (first x)
                      '(&allow-other-keys &key &rest &aux &optional))
              (if (eq (first x) '&optional)
                  (setf optional-section t)
                (setf accept-mv nil))
            (when accept-mv (push nil quick)))
          (push (first x) args))))))

(defun generate-funcall (fname arg-list quick)
  (cons fname
        (mapcar (lambda (arg)
                  (if (pop quick)
                      (list 'multiple-value-list arg)
                    arg))
                arg-list)))

(defmacro defun+ (fn-name arg-list &body body)
  (multiple-value-bind (b m q a) (parse-lambda-list arg-list)
    (if (null m)
        `(defun ,fn-name ,arg-list ,@body)
      (let ((fn (gensym (symbol-name fn-name))))
        `(progn
           (defun ,fn ,a (destructuring-bind ,b ,(cons 'list m)
                           ,@body))
           (defmacro ,fn-name (&rest args)
             (generate-funcall ',fn args ',q)))))))

So I could rewrite the painter program like this:

(defun+ transform (matrix &mv (fn &key current-m base-fn &allow-other-keys))
  (if (null current-m)
      (values
       (lambda (vectors painter)
        (funcall fn (final-calc vectors matrix) painter))
       :current-m matrix
       :base-fn fn)
    ;; inner call was another transform
    (let ((new-m (mat-mul current-m matrix)))
      (values
       (lambda (vectors painter)
         (funcall base-fn (final-calc vectors new-m) painter))
       :current-m new-m
       :base-fn base-fn))))

(defmacro rotate (angle &rest r)
  (let ((a (gensym)))
    `(let* ((,a ,angle)
            (m (make-array '(3 3) :element-type 'float
                           :initial-contents (list (list (cos ,a)(sin ,a) 
0.0)
                                                   (list (- (sin ,a))(cos 
,a) 0.0)
                                                   '(0.0 0.0 1.0)))))

(defmacro translate (x y &rest r)
  (let ((x-r (gensym))(y-r (gensym)))
    `(let ((,x-r (coerce ,x 'float))
           (,y-r (coerce ,y 'float)))
       (transform (make-array '(3 3) :element-type 'float
         :initial-contents (list (list 1.0 0.0 0.0)
            (list 0.0 1.0 0.0)
            (list ,x-r ,y-r 1.0))) ,@r))))
...

So that a combination like

(translate .5 0 (rot-45 (rot-180 (flip-horz *fish*))))

returns a function (1st value) that contains only one transfom matrix
w/o having to worry the user with the multiple values when putting
the pieces together.

--
Geoff 
From: Frank Buss
Subject: Re: multiple return values
Date: 
Message-ID: <1l2wb2cc0mh68$.1ts2isc6zemtk$.dlg@40tude.net>
Luke Crook wrote:

> Is this the reason why multiple values returned by VALUES cannot be
> used directly in a function call? For example:
> 
> (take-two-values (return-two-values))

you can use it in a function calls:

CL-USER > (defun foo (a b) (format t "~a ~a~%" a b))
FOO

CL-USER > (multiple-value-call #'foo (floor 11 3))
3 2
NIL


-- 
Frank Bu�, ··@frank-buss.de
http://www.frank-buss.de, http://www.it4-systems.de
From: Joe Marshall
Subject: Re: multiple return values
Date: 
Message-ID: <pstutrd4.fsf@ccs.neu.edu>
"Luke Crook" <····@balooga.com> writes:

> Kent M Pitman wrote:
>>
>> While it's normal (read: not a bug) to use multiple values,
>> it's not as common (statistically).  Consequently, it helps draw
>> attention to the unusual (though not abnormal) situation of using
>> both values, just as it's often useful to name other intermediate
>> values using LET variables. e.g.,
>
> Is this the reason why multiple values returned by VALUES cannot be
> used directly in a function call? For example:
>
> (take-two-values (return-two-values))

(take-two-values (if (some-condition)
                     (return-two-values)
                     (return-one-value))
                 (if (same-condition)
                     (return-no-values)
                     (return-one-value)))
From: Pascal Bourguignon
Subject: Re: multiple return values
Date: 
Message-ID: <87zmszxt0n.fsf@thalassa.informatimago.com>
chairam <·······@despammed.com> writes:

> Hi, I'm studying lisp
>
> Some function like:  truncate, floor, round,   return 2 values
>
> if you want to catch all values you have to use multiple-value-bind
> but:
> why 2 values and not a list of 2 values?
>
> I have my own opinion but appreciate others'

Multiple value results are returned in multiple registers: it's
faster, it avoids allocating new conses on the heap (which means slow
down to RAM or even to hard disk speed).

It's unfortunate that multiple value functions in Common Lisp have
names so long, because it doesn't reflect the time and space
performance of these functions.

You could use:

(defconstant mv-limit MULTIPLE-VALUES-LIMIT)
(defmacro defalias (new old) `(defmacro ,new (&rest args) (cons ',old args)))
(defalias mv-bind  MULTIPLE-VALUE-BIND)
(defalias mv-call  MULTIPLE-VALUE-CALL)
(defalias mv-list  MULTIPLE-VALUE-LIST)
(defalias mv-prog1 MULTIPLE-VALUE-PROG1)
(defalias mv-setq  MULTIPLE-VALUE-SETQ)

to get the feeling that mv-bind/values is more time-and-space
efficient than destructuring-bind/cons.



A second reason, is that if you want a list, you can always use: 

  (multiple-value-list (truncate 5 3)) ; or make it (mv-list (truncate 5 3))


-- 
__Pascal Bourguignon__                     http://www.informatimago.com/

Nobody can fix the economy.  Nobody can be trusted with their finger
on the button.  Nobody's perfect.  VOTE FOR NOBODY.
From: Kaz Kylheku
Subject: Re: multiple return values
Date: 
Message-ID: <1120753057.216171.146910@g14g2000cwa.googlegroups.com>
chairam wrote:
> Hi, I'm studying lisp
>
> Some function like:  truncate, floor, round,   return 2 values
>
> if you want to catch all values you have to use multiple-value-bind
> but:
> why 2 values and not a list of 2 values?

The storage locations that hold arguments and return values are not
first-class objects. They are data communication pathways. It's
important to be able to implement those pathways efficiently on a given
processor.

If the aggregate that holds return values were represented as a first
class list, then the program could retain a reference to that list. The
list would have to be allocated in the usual way and subject to garbage
collection.

The way it is right now, the program cannot get a handle on the place,
or places, which hold return values. It can only retrieve copies of the
values held in those inaccessible storage locations.

This is similar to how it works in other languages. For example in C, a
function can return a struct object. However, that returned struct
isn't a first class object. You cannot take the address of a member,
and if it contains an array, you therefore cannot use that array.

  struct foo { int x; int y[3]; };

  struct foo func(void);

  ...

     z = func().x;  /* okay to access x */

     func().x = 3;  /* error, returned struct isn't an lvalue */

     func().y;      /* error, cannot take address of any part */


These restrictions give the implementation a lot of freedom with
respect to implementing procedure linkage.

For instance, return values can be placed into registers, or pushed
onto the stack, or placed into a memory area that is reserved by the
caller, which could be on the stack.

None of these locations are programmer-visible first class objects in
the high level language; they are managed by the compiler. If registers
are used, the compiler takes care that the generate code knows what is
clobbered and what is saved. If return values are pushed on the stack,
the compiler ensures that everything is popped off the stack even if
the high level program doesn't use some or all of the return values.

Keeping the memory locations and the entire mechanism shrouded from the
programmer allows for optimizations. If a memory area is used for
return values, in principle it would be possible to allow the
programmer to see that area as an object in the high level language.
But that would just invite bugs, probably because that memory is quite
likely quickly disposed of and then reused again for another purpose.
For instance, suppose that the stack top is used for returning values.
As soon as the compiler-generated code which called the function cleans
those values off the stack, any subsequent evaluation can re-use the
same space by pushing values there. The programmer must use the
appropriate high level mechanism to ``rescue'' some or all of the
return values from that memory before it is gone.

> I have my own opinion but appreciate others'

That's wonderful! Now all you need is a time machine. :)
From: chairam
Subject: Re: multiple return values
Date: 
Message-ID: <2e7uc1p9clmaumolgj3ejjkk3lrf9iremf@4ax.com>
>Hi, I'm studying lisp
>[CUT]

tnx to all
i appreciate a lot all your answers

this was my idea:
return multiple values is more general  than return a list
the caller function must know what called function will return
(values, order...) and various function can do a different use of
returned values

but my main idea was:
return a list is more similar to invent a protocol than return
multiple values. I think this is not too much in the functional
philosophy and a better solution in this direction would be
encapsulation.

Bye
Chairam