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

Pattern destructing could assign values to existing variables #4235

Open
FMorschel opened this issue Jan 23, 2025 · 4 comments
Open

Pattern destructing could assign values to existing variables #4235

FMorschel opened this issue Jan 23, 2025 · 4 comments
Labels
request Requests to resolve a particular developer problem

Comments

@FMorschel
Copy link

Today we have patterns that allow us to deconstruct a variable:

class Class {
  int myField = 0;
}

void foo() {
  var instance = Class();
  if (instance case Class(myField: var myFieldValue)) {}
}

This only creates new variables after the :. I'd like to request a way for us to assign this to an existing variable. This could only work when we have this outside if/for lines, like:

late int myValue1;
late int myValue2;
late int myValue3;
if (test) {
  Class(myField := myValue1, otherField := myValue2, thirdField := myValue3) = instance;
} else {
  myValue1 = 0;
  myValue2 = 0;
  myValue3 = 0;
}

The := is only a representation here, I'm not certain this is the best solution. This would allow us to avoid creating multiple lines here.

@FMorschel FMorschel added the request Requests to resolve a particular developer problem label Jan 23, 2025
@FMorschel FMorschel changed the title Pattern destructing to assign values to existing variables Pattern destructing could assign values to existing variables Jan 23, 2025
@lrhn
Copy link
Member

lrhn commented Jan 24, 2025

A reason not to do that is that it makes pattern evaluation have side effects even if the pattern didn't match.

Currently patterns can only invoke ==, comparison operators and getters (including []), all of which are supposed to not have any side effects. Also switch patterns are allowed to cache the value of any such operation, so it will only be performed of the pattern matches.
That allows patterns to reorder checks.

The model for patterns is that you put a value in, and you get either "no match" or "match with these new variables" as result, but no side effects are intended, especially for the patterns that didn't match.
(You can break that with side-effecting getters or when clause, but you really shouldn't.)
If anything, a pattern could remember those variable changes, and only apply them off the pattern matched, so the := introduces a new variable that shadows the original in the test of the pattern and the when clause, but which is written back to the original variable of the pattern end up matching.

@tatumizer
Copy link

Your example doesn't require patterns - it can be written as a 1-liner:

var (myValue1, myValue2, myValue3) = test? (instance.myField, instance.otherField, instance.thirdField) : (0, 0, 0);

@FMorschel
Copy link
Author

Thanks @tatumizer, I'm aware. I just dislike the current syntax for that, hence this issue for allowing a different one 😁.

@tatumizer
Copy link

tatumizer commented Jan 27, 2025

FWIW, I prefer single-assignment (final) variables whenever possible. Simultaneous assignment is perfect for this.
If #260 is fully implemented (with "last value" rule), you will be able to write the above as

var (myValue1, myValue2, myValue3) = test? instance.{(myField, otherField, thirdField)} : (0, 0, 0);

What not to like here? :-)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
request Requests to resolve a particular developer problem
Projects
None yet
Development

No branches or pull requests

3 participants