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

Statements inside if conditions #443

Open
a-siva opened this issue Jul 8, 2019 · 6 comments
Open

Statements inside if conditions #443

a-siva opened this issue Jul 8, 2019 · 6 comments
Labels
feature Proposed language feature that solves one or more problems

Comments

@a-siva
Copy link

a-siva commented Jul 8, 2019

Statements inside control statement conditions to store it, check it and also scope it inside the control statement block would be very useful.

if((Point point = parseCursorPosition(chars)) != null) {
  // Do something with point
}

or

if(Point point = parseCursorPosition(chars); point != null) {
  // Do something with point
}

This feature is very popular in golang world.

Right now, this is possible:

Point point;
if((point = parseCursorPosition(chars)) != null) {
  // Do something with point
}

The only problem is this leaks the point outside its scope.

@a-siva a-siva added the feature Proposed language feature that solves one or more problems label Jul 8, 2019
@a-siva
Copy link
Author

a-siva commented Jul 8, 2019

Moved this issue under languages from dart-lang/sdk#37462

@lrhn
Copy link
Member

lrhn commented Jul 9, 2019

The feature allows a variable to be declared in an expression. The scope of the variable is the code dominated by that expression (up to the nearest enclosing block end, presumably).

Of the two formats, I think I prefer the "declaration as expression" over the "statement as part of expression". That is varFinalOrType id = expression would be treated as an expression, and the variable is in scope for the "rest" of the current statement block. The "rest' is quoted because we have to specify it formally, but it's basically and code that occurs after the evaluation of the expression.
Examples:

foo(var tmp = 42, tmp + 1, tmp + 2);

if (var success = test()) {
  ...
}
...
if (success) { moreSuccessStuff(); }

while ((var current = cursor.next) != null) {
  ...
  cursor = current;
}

and it can also be used to define syntactic sugar like e1 ?? e2 being equivalent to ((var tmp = e1) != null) ? tmp : e2.

If the syntax works out, I think it's a reasonable syntax for a let-like construct, even though it can only evaluate to itself. If you need a temporary variable, you can introduce it using this syntax the first time you need it, and then refer to it later.
It's not as flexible as let tmp = e1 in tmp != null ? tmp : e2 because you can't compute the result before you need it the first time, but it is shorter when you can replace one of the uses with the definition.

Whether

if((Point point = parseCursorPosition(chars)) != null) {
// Do something with point
}

should make point available after the if is a matter of taste. It definitely dominates the code after, but we could consider all control flow statements as implicitly being in a block of their own, so nothing leaves them. That is probably a good idea.

If we ever add an else branch to loops, then the condition variable might extend to that as well.

while ((Point p = nextPoint()).magnitude < 2) {
  plot(point);
} else {
  print("Point out of range: $p");
}

@lrhn
Copy link
Member

lrhn commented Jul 21, 2019

See also the Python "assignment expression" PEP (https://www.python.org/dev/peps/pep-0572/).

@munificent
Copy link
Member

Possibly not exactly what you had in mind, but with patterns, you can now do:

if(parseCursorPosition(chars) case var point when point != null) {
  // Do something with point
}

It will correctly scope point to just the then body of the if-case statement.

@rubenferreira97
Copy link

rubenferreira97 commented Sep 8, 2023

@munificent I am almost certain that you wanted to showcase pattern's full capacity 😉, but for future readers, you can do this:

if(parseCursorPosition(chars) case var point?) {
  // Do something with point
}

Also seeing @lrhn example, are there any obstacles preventing patterns from being used in loops like :

while (cursor.next case var current?) {
  // Do something with current
}

Or the syntax is a bit shady/does not work for all cases?

@munificent
Copy link
Member

are there any obstacles preventing patterns from being used in loops like :

No, no problems with supporting patterns in while loops, we just didn't get time to design and implement it. See: #2536

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
feature Proposed language feature that solves one or more problems
Projects
None yet
Development

No branches or pull requests

4 participants