Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Feature] Add support for tuple destructuring #485

Open
CC007 opened this issue Aug 28, 2023 · 9 comments
Open

[Feature] Add support for tuple destructuring #485

CC007 opened this issue Aug 28, 2023 · 9 comments

Comments

@CC007
Copy link
Contributor

CC007 commented Aug 28, 2023

Is your feature request related to a problem? Please describe.
Consider the following method:

auto returnTuple() {
    return "foo", 42, 13.37, (LocalDateTime.now());
}

When you want to use specific components of this tuple, it becomes quite verbose:

var tupleItems = returnTuple();

// You'll have to use the item1, item2, etc. to access the items
String s = tupleItems.item1;
int i = tupleItems.item2;
double d = tupleItems.item3;
LocalDateTime ldt = tupleItems.item4;
System.out.println("s = $s, i = $i, d = $d, ldt = $ldt");

// or directly, which makes the line a bit longer
System.out.println("s = ${tupleItems.item1}, i = ${tupleItems.item2}, d = ${tupleItems.item3}, ldt = ${tupleItems.item4}");

Describe the solution you'd like
It would be nice if manifold supported tuple destructuring, like so:

var (s, i, d, ldt) = returnTuple();
System.out.println("s = $s, i = $i, d = $d, ldt = $ldt");

This would also be a nice feature for interacting with records, when you want to more formally define and document the data structure. Consider this:

/**
 * This describes a person
 * 
 * @param name name of person
 * @param age age of person
 */
record Person(
    String name, 
    int age
) {}

...

String doSomethingWithPerson(PersonSupplier personSupplier) {
    var (name, age) = personSupplier.getPerson();
    return "$name is $age years old";
}

In the case that the tuple/record has more items than the destructuring requests, the extra items should be ignored. Maybe _ could be used for explicitly ignoring/skipping certain elements during destructuring, like so:

var (s, _, d) = returnTuple();
System.out.println("s = $s, d = $d");

Describe alternatives you've considered
The syntax could also be like this for when you don't want to use type inference:

(String s, int i, double d, LocalDateTime ldt) = returnTuple();

Destructuring classes in general would technically also be possible, but would be way more complex and therefore out of scope, due to having to decide which fields/methods to make available as items, inheritance and an unclear ordering of the items. Records are straight-forward: they have no inheritance, all items are specified as record parameters, in a specific order and they have a getter by default.

Additional context
See documentation for tuple deconstructing/destructuring in other languages:

JEP for java 21 for destructuring records when using instanceof: https://openjdk.org/jeps/440
preview JEP for java 21 for unnamed patterns and variables: https://openjdk.org/jeps/443

PS: why are the extra brackets needed around LocalDateTime.now()? It doesn't compile without them.

@rsmckinney
Copy link
Member

rsmckinney commented Aug 29, 2023

Hi @CC007. All great feature requests.

Regarding, the LocalDateTime.now() question, I'm not seeing that.

  auto returnTuple() {
    return "foo", 42, 13.37, LocalDateTime.now();
  }

Works fine for me, both in IJ editor & compilation.

@CC007
Copy link
Contributor Author

CC007 commented Aug 29, 2023

I'm getting this:
afbeelding

So without brackets compiles alright, but the item isn't usable as item4.

It got compiled to this instead:
afbeelding

As you can see, it is compiled to now instead item4.

@rsmckinney
Copy link
Member

Right. That is intentional. Tuples infer labels from the expressions if possible. In this case the method name.

@CC007
Copy link
Contributor Author

CC007 commented Aug 30, 2023

It is a bit unintuitive though that item4 couldn't be used as well as an alias.

@rsmckinney
Copy link
Member

It is a bit unintuitive though

Yep. But I think label inference tends to be more useful than not because:

  1. Code completion.
    I would think the vast majority of manifold users are developing with IJ / Android where the tuple items are at your fingertips.

  2. Explicit labels.
    Unless the labels are apparent from the expressions (refs to fields, locals, properties, etc.) direct labels are best.

  3. Low arity.
    Most tuples consist of two items. If you’re using tuples, you probably like labeling your two items explicitly, otherwise you’d probably prefer a ‘Pair’ class or the like. Just my take on it.

@CC007
Copy link
Contributor Author

CC007 commented Aug 31, 2023

Those are indeed all good reasons why label inference is intuitive to have. What I found unintuitive though was not that there is inference, but the lack of the item4. I'm a proponent of having both.

@rsmckinney
Copy link
Member

Sure, that makes sense. Always have the itemN syntax regardless of the labels. I like it.

Would be interesting to make array operator work where a compile-time constant index expression would determine the type:

String item1 = tuple[0];
int item2 = tuple[1];

lol

@CC007
Copy link
Contributor Author

CC007 commented Sep 2, 2023

Agreed. Actually wanted to add that as a feature request too, but considering the type differences, I could see that being an issue.

@CC007
Copy link
Contributor Author

CC007 commented Mar 17, 2024

Any progress on implementing this feature?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants