Multiple return values
Remi Forax
forax at univ-mlv.fr
Mon Jan 14 11:20:43 UTC 2019
You can have both !
This is basically what we are doing with lambdas, you have a structural syntax + a named type that are bound together using inference.
Let say we have a tuple keyword that means, value + record + constructor/de-constructor
tuple Range(int lo, int hi) { … }
then you can write:
Range method(int x) {
return (x, x + 1); // the compiler infers "new Range(x, x + 1)"
}
and also
var (x, y) = method(); // the compiler uses the de-constructor or the record getters if there is no de-constructor
With Stream<???> s = aStream.map(Lukas::method), ??? is a Range,
and if someone want to use the tuple syntax inside a call to map(), a type as to be provided,
by example
aStream.<Range>map(x -> (x, x + 1)).collect(...)
Rémi
----- Mail original -----
> De: "Brian Goetz" <brian.goetz at oracle.com>
> À: "Lukas Eder" <lukas.eder at gmail.com>
> Cc: "amber-spec-comments" <amber-spec-comments at openjdk.java.net>
> Envoyé: Vendredi 11 Janvier 2019 17:07:43
> Objet: Re: Multiple return values
> While I understand where you’re coming from, I think multiple return is likely
> to be both more intrusive and less satisfying than it first appears.
>
> First, it’s a relatively deep cut; it goes all the way down to method
> descriptors, since methods in the JVM can only return a single thing. So what
> you’re really asking the compiler to do is create an anonymous record (whose
> denotation must be stable as it will be burned into client classfiles.) That’s
> the “more intrusive” part.
>
> The “less satisfying” part is that if you can return multiple values:
>
> return (x, y)
>
> and then obviously you need a way to destructure multiple values:
>
> (x, y) = method()
>
> (since otherwise, what would you do with the return value?)
>
> But here’s where people will hate you: why can I use tuples as return values,
> and destructure them into locals, but not use them as method arguments, or type
> parameters? Now I can’t compose
>
> someMethod(method())
>
> because I can’t denote the return type of method() as a parameter type. And I
> can use your multiple-returning method in a stream map:
>
> Stream<T> s = aStream.map(Lukas::method) // stream of what?
>
> When we tug on this string, we’ll be very disappointed that it’s not tied to
> anything.
>
>
> Instead, what you can do is expose records in your APIs:
>
> ```
> class MyAPI {
> record Range(int lo, int hi) { … }
>
> Range method() { … }
> }
> ```
>
> and now a caller gets a Range back, which is a denotable type and whose
> components have descriptive names.
>
> You say you don’t want to do this because creating new types is so much work.
> Is the one-line declaration of `Range` above really so much work? (Ignoring
> the fact that returning a Range is far more descriptive than returning an (int,
> int) pair.)
>
>
>
>> On Jan 11, 2019, at 10:57 AM, Lukas Eder <lukas.eder at gmail.com> wrote:
>>
>> Hello,
>>
>> I'm referring to the exciting proposed new features around destructuring
>> values from records and other types as shown here:
>> https://cr.openjdk.java.net/~briangoetz/amber/pattern-match.html#pattern-bind-statements
>>
>> The example given was:
>>
>> Rect r = ...
>> __let Rect(var p0, var p1) = r;
>> // use p0, p1
>>
>> This is a very useful construct, which I have liked using in other
>> languages a lot. Just today, I had a similar use case where I would have
>> liked to be able to do something like this, but without declaring a nominal
>> type Rect. Every now and then, I would like to return more than one value
>> from a method. For example:
>>
>> private X, Y method() {
>> X x = ...
>> Y y = ...
>> return x, y;
>> }
>>
>> I would then call this method as follows (hypothetical syntax. Many other
>> syntaxes are possible, e.g. syntaxes that make expressions look like
>> tuples, or actual tuples of course):
>>
>> X x, Y y = method();
>>
>> The rationale is that I don't (always) want to:
>>
>> - Modify either type X or Y, because this is just one little method where I
>> want to indicate to the call site of method() in what context they should
>> interpret X by providing a context Y
>> - Wrap X and Y in a new type, because creating new types is too much work
>> - Wrap X and Y in Object[] because that's just dirty
>> - Rely on escape analysis for some wrapper type (minor requirement for me)
>> - Assign both X and Y. Something like "X x, _ = method()" or "_, Y y =
>> method()" would be useful, too.
>>
>> I was wondering if in the context of all the work going on in Amber around
>> capturing local variables, etc. if something like this is reasonably
>> possible as well in some future Java.
>>
>> This is possible in Python. Go uses this syntax to return exceptions.
>>
>> Thanks,
> > Lukas
More information about the amber-spec-experts
mailing list