Skip to content

Ability to return and throw from ?? expression. #3293

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

Closed
BirjuVachhani opened this issue Aug 19, 2023 · 4 comments
Closed

Ability to return and throw from ?? expression. #3293

BirjuVachhani opened this issue Aug 19, 2023 · 4 comments
Labels
feature Proposed language feature that solves one or more problems state-duplicate This issue or pull request already exists

Comments

@BirjuVachhani
Copy link

I am familiar with Elvis operator ?: Kotlin. The dart equivalent of this would be ?? in most cases. While ?? works great, there is no way to return from it or throw in the same line of the expression without writing a bit of boilerplate code.

Example:

Dart as of now,

Version checkHasVersion(Map<String, dynamic> json) {
  final versionString = json['current'];
  if (versionString == null) throw Exception('Not found'); // extra line for null check.

  return Version.parse(versionString);
}

With ability to throw from ?? expression

Version checkHasVersion(Map<String, dynamic> json) {
  final versionString = json['current'] ?? throw Exception('Not found');

  return Version.parse(versionString);
}

Same for returning values:

Version checkHasVersion(Map<String, dynamic> json) {
  final String versionString = json['current'] ?? return Version(0, 0, 0);

  return Version.parse(versionString);
}

Kotlin version:

fun test(map: Map<String, Int>): Int {
    val version: Int = map["version"] ?: return -1
    return version + 2
}
@BirjuVachhani BirjuVachhani added the feature Proposed language feature that solves one or more problems label Aug 19, 2023
@lrhn
Copy link
Member

lrhn commented Aug 19, 2023

See #3052 for return.

You can use throw, it just needs parentheses:

  final versionString = json['current'] ?? (throw Exception('Not found'));

Closing as duplicate of #2025.

@lrhn lrhn closed this as completed Aug 19, 2023
@lrhn lrhn added the state-duplicate This issue or pull request already exists label Aug 19, 2023
@BirjuVachhani
Copy link
Author

I see. Thanks for the explanation and links to other related issues @lrhn.

However, I am wondering why these parenthesis are needed? It seems less intuitive.

@lrhn
Copy link
Member

lrhn commented Aug 20, 2023

The reason the parentheses are needed is that someone argued, back whenthrow was made an expression, that it should bind weakly to its operand, which meant that it became a special <expression> instead of a prefix-operator.
That was me, I was wrong. Sorry.

That meant that there are places in the grammar it cannot occur. We have actually fixed that for conditional expressions. According to the spec grammar, you should be able to have a throw as the operand of a conditional expression, because <expressionWithoutCascade> can now be a throw. So no parentheses needed.

@BirjuVachhani
Copy link
Author

Ah, I see. I didn't know that conditional expressions could have it w/o {}. I just tried it and it works as expected and I like it. Thanks!

Would it be possible to have the same behavior for ?? too? no parentheses? Would be great actually! I hate whenever I have to wrap something in parenthesis specially when it affects the readability of the code.

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 state-duplicate This issue or pull request already exists
Projects
None yet
Development

No branches or pull requests

2 participants