Continue in switch

Brian Goetz brian.goetz at
Tue May 8 19:31:37 UTC 2018

This is not an urgent issue for the expression switch work, but I'd like 
to get some ideas about how we will want to handle guards in pattern 
switch, as we may want to lay some groundwork in the form of warnings now.

Initially we considered explicit guards:

     case Foo(var x, var y)
         where x <= y: ...

(Note that there is a connection between nested patterns and guards; a 
nested pattern P(Q) is equivalent to P(x) with a guard of x matches Q.)

While this is semantically attractive (the guard condition is 
declarative), I worry that it is not likely to be very satisfying in 
practice.  In toy examples, it looks great, but as examples expand to a 
more realistic scale, the pattern, guard, and imperative consequence can 
easily mush together.  For example:

     case Point(var x, var y)
         where x > 0 && y > 0 && x < y -> x + y;

You can try reformatting:

     case Point(var x, var y)
         where x > 0 && y > 0 && x < y
             -> x + y;

but its not that much better.  So, I'm pretty down on this approach 
right now, and I think several others are as well.

An alternative is to provide an imperative means to refine the switch 
selection.  The obvious choice is to give "continue" semantics within a 

     case Foo(var x, var y):
         if (x > y)
             continue;  // keep processing at next case
         foo(x, y);

Continuing in a switch means "keep testing the target against case 
labels, starting with the next case label."  This is only a short hop 
from the current notion of continue in for/while loops.

Of course, compatibility raises its ugly head.  You could have a switch 
today with continue-in-switch-in-for:

     for (...) {
         switch (x) {
             case 0: continue;  // valid today, means continue the loop

This code works today, which means a continue in a switch in a loop 
would be ambiguous, and would require a label.

As a means of mitigation, we could also allow the syntax "continue 
switch" or "continue while" to mean "continue from the innermost 
switch/while".  This is arguably more readable, and reduces the number 
of cases where a label would be required.

If we're going to go the "continue" route, we might want to consider 
warning now in cases where there would be an ambiguity, suggesting that 
the user use a labeled continue, to move codebases in the right direction.

If continue is the right notion, our choice is essentially between:
  - drive towards continue in switch working like it does in everything 
else, and deal with ambiguities (switch in loop) as they come up;
  - drive towards something that looks sufficiently different from 
"naked" continue (continue with label, "continue switch") in switches, 
and accept there will be a permanent seam (in switch you do it this way, 
in loops, this other way.)

More information about the amber-spec-experts mailing list