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.go...@oracle.com> > À: "Lukas Eder" <lukas.e...@gmail.com> > Cc: "amber-spec-comments" <amber-spec-comme...@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.e...@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