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

jdk 12 like switch statement #27

Closed
thefuzzyorange opened this issue Sep 13, 2018 · 9 comments
Closed

jdk 12 like switch statement #27

thefuzzyorange opened this issue Sep 13, 2018 · 9 comments
Labels
request Requests to resolve a particular developer problem

Comments

@thefuzzyorange
Copy link

thefuzzyorange commented Sep 13, 2018

As a proposal I'd like to suggest Dart to implement enhancements to the switch statement in the same manner as Java is doing with JDK 12.

The enhancements allow for

  1. More concise code,
  2. Removing the need of a break statement in certain situations
  3. Allowing case statements to return a value.

The new switch features are outlined in good detail here:
https://www.javacodegeeks.com/2018/09/jdk-12-switch-statements-expressions.html

All examples are from article above. I've just added them here from a high level point of view

Traditional Switch

String numericString;
switch (integer)
   {
      case 1 :
         numericString = "one";
         break;
      case 2 :
         numericString = "two";
         break;
      case 3:
         numericString = "three";
         break;
      default:
         numericString = "N/A";
   }

JDK 12 Enhanced Switch

   switch (integer)
   {
      case 1 -> numericString = "one";
      case 2 -> numericString = "two";
      case 3 -> numericString = "three";
      default -> numericString = "N/A";
   }

JDK 12 : New switch Expression Returning Value via break

   final String numericString =
      switch (integer)
      {
         case 1 :
            break "uno";
         case 2 :
            break "dos";
         case 3 :
            break "tres";
         default :
            break "N/A";
      };

JDK 12 : New switch Expression Returning Value via Label Rules

   final String numericString =
      switch (integer)
      {
         case 1 -> "uno";
         case 2 -> "dos";
         case 3 -> "tres";
         case 4 -> "quatro";
         default -> "N/A";
      };

JDK 12 : Multiple Constants Can Be Specified for a Single case

   final String numericString =
      switch (integer)
      {
         case 0 -> "zero";
         case 1, 3, 5, 7, 9 -> "odd";
         case 2, 4, 6, 8, 10 -> "even";
         default -> "N/A";
      };
@Hixie
Copy link

Hixie commented Sep 13, 2018

"Enhanced Switch" seems to be the same as removing the redundant break, which I agree seems valuable.
The next two seem to boil down to making "switch" into an expression, rather than a statement. In general this might be useful in the "ui as code" paradigm (cc @munificent). Other people have asked for "if" to be an expression, or "while"/"for"/"do".
The last one seems to be possible already, using case 1: case 3: case 5:, though I must admit that as a programmer from the Knuth school, I can certainly get behind Pascal-style 1, 3, 5:. Pascal goes even further by avoiding the case (since each selector only has one statement associated with it, rather than a block as in C-like languages), and allowing ranges for ordinals (e.g. monday .. friday, assuming that these are values from an enum).

@munificent
Copy link
Member

What I really think we should do is pattern matching, including full destructuring of objects and collections. That covers all of the use cases of switch and then some.

I'm not currently looking at that as part of the "UI as code" changes because this kind of control flow doesn't seem to be a large component of Flutter UI code.

@mit-mit mit-mit added the request Requests to resolve a particular developer problem label Nov 8, 2018
@berwyn
Copy link

berwyn commented May 30, 2019

Pardon the intrusion and raising this from the depths of the netherrealms, but I'd love to note a good use-case for a switch expression and/or pattern matching!

I'm just diving into Flutter and following some tutorials that recommend the BLoC pattern for building apps. Of note, given a Bloc<Event, State>, one might find a function like such:

Stream<State> mapEventToState(Event e) async {
  if (e is Foo) {
    yield SomeState( ... );
  } else if (e is Bar) {
    yield OtherState( ... );
  } else if ....
  } else {
    yield ErrorState();
  }
}

or even in many examples the yet more verbose pattern of

if (e is Foo) {
  yield SomeState();
  return;
}
if (e is Bar) {
  yield OtherState();
  return;
}
...

As written, this is very wordy, especially if your Bloc can handle many types of events! If we look at the state of the art in other languages, constructs like C# 8's switch expression or Rust's match expressions leap out as a fantastic way to clean these up. For example, in C# (and forgive me for making the sample more C#-ey):

Iterable<State> MapEventToState(Event e)
{
    yield return e switch
    {
        Foo _ => new SomeState( ... ),
        Bar _ => new OtherState( ... ),
        ...
        _ => new ErrorState()
    }
}

That is, in my opinion, a major improvement! A lot less noise, more scannable, and much less repetition. Especially handy in this case is the ability write yield (or yield return in C#'s case) only once, saving us from potentially tricky bugs where we introduce a check for a new event type but forget to yield the resulting state.

@wrozwad
Copy link

wrozwad commented Jun 26, 2019

Based on Kotlin when expression it will be awesome to saw one day switch with arbitrary expressions, in range and instance checks, etc. like:

switch (dynamic x) {
    is! Integer -> print("x is not an integer")
    isSpecialMagicNumber(x) -> print("x is magic number from function")
    in 1..10 -> print("x is in the range")
    in validNumbers -> print("x is in array")
    !in 10..20 -> print("x is outside the range")
    else -> print("none of the above")
}

@eernstg
Copy link
Member

eernstg commented Dec 16, 2019

@thefuzzyorange, maybe you could re-target this issue to be about improvements of the Dart switch statement in a broader sense (that is, change the title to something like 'Improve the switch statement')?

Then we could gather several issues about switch here, and maintain a good overview of the proposals: #307, #703, #745.

@He-Pin
Copy link

He-Pin commented Dec 24, 2019

Scala one is better

@AKushWarrior
Copy link

AKushWarrior commented Sep 18, 2020

Is there a status on this issue? Can we revive it?

I think @sosite made an excellent point; Kotlin's when essentially encapsulates everything you could want:

  • switch (when) as expression
  • Uses == by default, but allows for insertion of custom logic
  • Allows for multiple cases to be bundled (Pascal style)

There's also another issue floating somewhere about not having to retype the first section of an enum in every case statement. I'll link it if I find it (EDIT: #357), but that also seems more relevant when we can bundle cases.

Heck, even JDK 14 switch is getting pretty close to ideal.

@AKushWarrior
Copy link

AKushWarrior commented Sep 18, 2020

Also: @munificent I think this could easily be part of the UI as code paradigm.

var myApp = MaterialApp (
    // some other stuff here
    home: switch (getBreakpoint()) { //where getBreakpoint is a enum of type BreakPoint
         case .xL -> xLHomePage();
         case .L -> LHomePage();
         case .mL -> mLHomePage();
         case .m -> mHomePage();
         case .sM -> sMHomePage();
         case .s -> sHomePage();
    }
)

This a small and somewhat contrived example, but it serves the purpose. If you have to switch between 3+ widgets based on a certain value, this is pretty time-saving.

@munificent
Copy link
Member

Closing this because switch expressions are now enabled in the bleeding edge Dart SDK. 🎉

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

9 participants