[racket] Multiple return values

From: Zayr Okale (zayr.okale at gmail.com)
Date: Fri Dec 16 06:52:32 EST 2011

On 15/12/2011 21:17, Tomasz Rola wrote:
> On Thu, 15 Dec 2011, Zayr Okale wrote:
>> I even do understand what multiple return values are useful for in CL: "okay,
>> the function calculates other potentially useful values anyway, so no reason
>> not to make them available".
>> Unfortunately, this scenario doesn't apply to Racket. And this is exactly what
>> prompted my question. Since one of the reasons behind multiple return values
>> is, as David Van Horn pointed out, symmetry with multiple input values
>> (function arguments), then why optional input values are allowed, but optional
>> output values aren't?
> This question is probably better asked to people behind RnRS. I was unable
> to give you any interesting examples with Scheme, because I didn't know
> them. Actually, I was a bit unsure about this multiple values stuff
> myself, as I had been reading R5RS some time ago (I am yet to find time
> for R6RS, so maybe there is more about values, but I don't know right
> now).

Technically, R6RS section 11.15 says the behavior is undefined in this 
case. Racket could choose to silently ignore extra values while staying 
compatible, and given that Racket considers #lang rNrs separate 
languages from the default one, it is even less obliged to honor RnRS 
requirement here. Not to mention this change won't break the existing code.

> After I exchanged punches with CL, I've got a bit better understanding of
> the issue. Or so I hope.
> Your question sounded like one of more general nature, which is why I
> allowed myself to do this CL/C intrusion here.

In some sense, it is. I can understand how and why to use multiple 
values in CL, but I cannot directly apply this to Racket, since I am 
prohibited from ignoring extra values without extra effort. To continue 
the talk about symmetry, if the language doesn't support optional input 
values and I want to add support for them via macros, I need to wrap one 
or two things, that is, the function definition forms. If it doesn't 
support optional output values, however, I have to wrap every function 
call that uses them. This is O(n) vs O(1) effort, so to speak.

>> The situation when all the return values are of equal importance, yet
>> returning a struct or a list is not convenient is, IMHO, quite rare.
> I don't want to bet on this :-) .
> I think that in some cases you may emulate values by operating on list.
> Like, return a list of values and later use apply.
> However, once you have to produce list of specified size, it becomes
> inconvenient, IMHO. Because no matter what you want, you have to make this
> one specific list and later go through it to access the elements (this can
> be optimized, but one shouldn't count on such happy end).

On the other hand, allowing to ignore extra values doesn't seem to 
create obvious optimizations problems and allows the same use while 
allowing some more applications.

> So I think using list/struct forces an overhead when later you want to
> make use of the values. On the other hand, with values (again, sorry for
> CL), one can have:
> [2]>  (multiple-value-bind (f r) (floor 130 11) (list f r))
> (11 9)
> This is from CL HyperSpec. Here, your data is "inserted" into your
> namespace, and this can be paired with (declare (ignore ...)) to make it
> perform better.

In the simplest cases in CL I can ignore extra values for free (without 
extra wrappers or any other code clutter). In Racket I cannot, and this 
is what prompted my question: why not do it the CL way?

> I keep an eye on Racket but I don't know it too well (just one
> non-trivial program bettered with profiler and few smaller ad hoc pieces
> over few years period), so I am unsure how much sense is there in using
> values in it.

I have the suspicion this behavior has been simply inherited from 
Scheme, since PLT Scheme was originally a Scheme implementation (I 
think). IIUC, PLT Scheme was renamed to Racket because the team was 
feeling it isn't Scheme anymore. So, since it is now (more) free from 
RnRS obligations, this feature can be implemented based on what's better 
for Racket, as opposed to what RnRS says is better for Scheme. I feel 
the only thing lost in the transition from RnRS way to CL way would be 
the developers' time and effort spent implementing the change, while a 
degree of convenience will be gained by all Racket users.

Posted on the users mailing list.