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

'Switch-case' shorthand syntax #703

Closed
Den163 opened this issue Nov 23, 2019 · 13 comments
Closed

'Switch-case' shorthand syntax #703

Den163 opened this issue Nov 23, 2019 · 13 comments
Labels
feature Proposed language feature that solves one or more problems patterns Issues related to pattern matching.

Comments

@Den163
Copy link

Den163 commented Nov 23, 2019

This is about an antique C-syntax construction like a 'switch-case' statement. In my experience, the use case of it is often like a map some value 'A' to another value 'B'. Therefore, some modern languages try to simplify this case (influenced by functional languages like Haskell, I think). So it will be nice if Dart would have something like that.
For example, Kotlin has 'when' operator :

val aStr = when (a) {
    1 -> "first"
    2 -> "second"
    3 -> "thrird"
    else -> "${a}th"
}

C# 8.0 has something the same:

a switch 
{
    1 => "first",
    2 => "second",
    3 => "third",
    _ => $"{a}th",
};

Notice that in both of languages improved 'switch-case' is not a statement, but an expression that
prevent us to wrap statement into the function to get this sort of a 'mapping'.

In Dart to get this result, I need to:

  1. Wrap all values in the map and check in the getter function - is the key argument exist in the map:
final _values = const {
  1 : "first"
  2 : "second"
  3 : "third"
}

String getValue(final int a) => _values[a] ?? "${a}th";

Or

  1. Write so cumbersome, a C-like switch statement function:
String getValue(final int a) {
  switch (a) {
    case 1: return "first";
    case 2: return "second";
    case 3: return "third";
    default: return "${a}th"
  }
}

In other cases in my opinion it's better to avoid an antique 'switch-case' statement to improve code readeablitiy.

@Den163 Den163 added the feature Proposed language feature that solves one or more problems label Nov 23, 2019
@lrhn
Copy link
Member

lrhn commented Nov 25, 2019

You can write the map literal inline, so it would be:

String getValue(final int a) => const {
  1 : "first",
  2 : "second",
  3 : "third",
}[a] ?? "${a}th";

That's not too far from the switch. It does require the expressions to be constant, or if the map is not constant, then all of the expressions are evaluated on each use.

Making switch into an expression matches with similar requests for if and other statements. I am not too optimistic about changing statements to expressions in general, but a way to embed a statement in an expression, without wrapping it in a new function, might be useful.

@mnordine
Copy link
Contributor

mnordine commented Nov 29, 2019

I think this has been discussed in many existing issues. I think this proposal may satisfy you?

#546

It mentions switch expressions and links to 2 related issues. It also brings them into a more comprehensive context.

@GregoryConrad
Copy link

Here's a clean workaround when dealing with an enum and you want to be sure you cover all enum options (which unfortunately isn't possible with the Map workaround):

final resultOfExpression = (){
  switch(value) {
    case SomeEnum.foo:
      return 'fizz';
    case SomeEnum.bar:
      return 'buzz';
  }
}();

Worth mentioning: in lots of use cases, the above can be achieved better by using enhanced enums with a member field for whatever you are trying to access. Sometimes though, this little trick can come in handy.

@munificent munificent added the patterns Issues related to pattern matching. label Sep 26, 2022
@gaaclarke
Copy link

Dart already does have a switch expression of sorts with nested ternary operators.

final x = y ? 1 : (z ? 2 : (w ? 3 : 4));

It's cumbersome but it is the only way you can initialize const fields. In that sense a switch expression could just be syntactic sugar on the front end that transforms to nested ternary operators (and hopefully does a completeness check).

Getting a bit philosophical, if you don't mind, Dart was designed to be an optimal expression of well known languages at the time it was made. It was designed, imo, to make it an easy transition from another popular languages and I think it did a marvelous job at that. Right now we are experiencing a great shift to the next generation of languages, Objc->Swift, Java->Kotlin, C++->Rust, so the question becomes "Does Dart want to maintain familiar for the last generation of languages, or does it want to be familiar to the next generation of languages?" What was odd when Dart was designed is now becoming common place. A "switch expression" (which my guess actually comes from ML's match) appears to be more and more common and it missing from Dart is going to become more and more of an oddity, adding to the barrier-of-entry that is being constructed over time by the shift in programming languages.

@gaaclarke
Copy link

It also looks like this issue is just a version of #27

@munificent
Copy link
Member

munificent commented Sep 30, 2022

Note that with the in-progress patterns proposal, you can write:

var aStr = switch (a) {
  case 1 => "first";
  case 2 => "second";
  case 3 => "thrird";
  case _ => "${a}th"
};

@Levi-Lesches
Copy link

Would be cool if there could be a list somewhere of all the issues that will be fixed with records/other featuers so they can all be closed at once

@munificent
Copy link
Member

I'm trying to label all issues related to patterns and records with patterns or records. There's also a pair of "later" labels for issues related to those that likely won't be addressed in the initial release. It's probably not entirely comprehensive because there isn't always a perfect mapping between a user request and a specific language feature, but most of them should be in there.

@munificent
Copy link
Member

Closing this because records and patterns are now enabled by default on the main branch of the Dart SDK! 🎉

@stefan-sherwood
Copy link

A succinct and readable way to do this is:

var aStr = {
  1: "first",
  2: "second",
  3: "third"
}[ which ] ?? "${which}th";

@erayerdin
Copy link

Note that with the in-progress patterns proposal, you can write:

var aStr = switch (a) {
  case 1 => "first";
  case 2 => "second";
  case 3 => "thrird";
  case _ => "${a}th"
};

case in this expression causes compile-time error. Remove them.

@mateusfccp
Copy link
Contributor

Note that with the in-progress patterns proposal, you can write:

var aStr = switch (a) {
  case 1 => "first";
  case 2 => "second";
  case 3 => "thrird";
  case _ => "${a}th"
};

case in this expression causes compile-time error. Remove them.

Yes, not only the case keyword, but the ; too.

In Dart 3.0, this is the correct syntax:

var aStr = switch (a) {
  1 => "first",
  2 => "second",
  3 => "thrird",
  _ => "${a}th",
};

@munificent
Copy link
Member

Life comes at you real fast! :D Yes, we change the switch expression syntax after I wrote that comment. Thanks for the corrections.

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 patterns Issues related to pattern matching.
Projects
None yet
Development

No branches or pull requests

10 participants