
On 17 January 2011 15:04, Luc Goossens <luc.goossens@cern.ch> wrote:
Hi all,
Thanks to everybody for your feedback! So I guess the answer to my question (which - I noticed just now - did not end with a question mark), is ... no.
If your function is returning a bunch of related values in a tuple, and that tuple keeps changing as you re-design the code, that's a code smell.
the use cases I have in mind are the functions that return a set of weakly related values, or more importantly report on different aspects of the calculation; an example of the first is a divmod function that returns the div and the mod while callers might only be interested in the div; examples of the latter are the time it took to calculate the value, possible warnings that were encountered, ...
like the good old errorcode/stdout/stderr trio
[various workarounds suggested]
the problem with (all) the workarounds that were suggested is that they help with migrating from 2 to more return values; for the 1 to 2 case (the most common case) they don't help a lot, as the amount of work to put the workaround in place exceeds the amount of work to cope with the migration directly; I would say it is a requirement that the simple case of single variable gets single (or first) return value, retains its current simple notation
If the system automatically ignored "new" return values (for whatever "new" might mean), I think it would be too easy to miss return values that you don't mean to be ignoring.
this I guess is only valid in the case where multiple return values are so strongly related they probably should be an object instead of a bunch of values
So it would be neat if you could do:
(a, b, c=3) = func(...)
or adding keywords to the mix
a, b, c = kw1, d = kw2 (defval2) = function(...)
now for the can of worms ...
- one would need some syntactic means to distinguish the returning of two values from the returning of a single pair with two values - there's a complication with nested function calls (i.e. fun1 ( fun2(...), fun3(...)); the only simple semantic I could associate with this, is to simply drop all return values except for the first, but that is incompatible with returning the full return value of a function without needing to manipulate it
LISP has a notion of multiple return values. I can't easily find an authoritative reference, but here is a short explanation: http://abhishek.geek.nz/docs/features-of-common-lisp/#Multiple_values Based on this, you could define a decorator class: class multiple_values: def __init__(self, f): self.f = f def __call__(self, *args, **kwargs): return self.f(*args, **kwargs)[0] def all_values(self, *args, **kwargs): return self.f(*args, **kwargs) @multiple_values def div(x, y): return x//y, x%y Then:
q = div(10, 3) 3 q, r = div.all_values(17, 5)
-- Arnaud