Multiple return values

Brian Goetz brian.goetz at oracle.com
Fri Jan 11 16:08:17 UTC 2019


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