[pattern-switch] Opting into totality

Brian Goetz brian.goetz at oracle.com
Mon Aug 31 20:05:12 UTC 2020


Everything you say would be a fine way to make a new language from 
scratch.  But, having made the choice to rehabilitate switch, and not do 
a "let's fix all the switch mistakes of the past" snitch construct, I 
think this approach would be pushing it too far, and I strongly doubt 
we'd get the benefit we are looking for.

> Ok, here i should have use "right default" instead of "right 
> behavior", you are right that it's not about the behavior, my bad on 
> that.

OK, good.  One thing we've learned, though, is that trying to fix the 
defaults after 25 years often makes things worse.  The benefit has to be 
super-huge to justify the next few years of confusion.  Here, I don't 
see it.





On 8/31/2020 3:57 PM, forax at univ-mlv.fr wrote:
>
>
> ------------------------------------------------------------------------
>
>     *De: *"Brian Goetz" <brian.goetz at oracle.com>
>     *À: *"Remi Forax" <forax at univ-mlv.fr>
>     *Cc: *"amber-spec-experts" <amber-spec-experts at openjdk.java.net>
>     *Envoyé: *Lundi 31 Août 2020 17:51:54
>     *Objet: *Re: [pattern-switch] Opting into totality
>
>     What you're suggesting is that we should treat statement switch
>     partiality as a legacy behavior of existing switches on {
>     primitives, boxes, strings, and enums }, and then say the rest of
>     the switches are total.  (I must observe that the irony that you'd
>     raise the spectre of "snitch" and then in the same breath make a
>     proposal like this is pretty "total".)
>
>     Not only is this a far more intrusive change, but it also ignores
>     something fundamental: partiality for statement switches _is a
>     feature, not a bug_.  A partial switch is like an `if` without an
>     `else`; no one thinks such things are mistakes, and a rule that
>     required an `else` on every `if` would not be appreciated.  I
>     appreciate the attempt at symmetry, and all things being equal
>     that would be nice, but I don't think all things are equal here. 
>     I think this asks far too much of users to stretch their mental
>     model in this way -- nor do I think it is worth the benefit, nor
>     am I even convinced we'd actually even achieve the benefit in
>     practice. 
>
>
> 'if' and 'switch' are dual, 'if' is oriented toward doing one test on 
> a value and 'switch' is oriented to doing several tests on the same value.
> So a partial switch is not like an 'if', it's like a cascade of 
> 'if/else' so forcing to have an 'else' when you have a cascade of 
> 'if/else' seems not as bad as your are suggesting.
>
> Yes, it's a more intrusive change but it using the playbook on how to 
> grow a language, to avoid to add features on top of features to the 
> point the language is too hard to understand, the idea is that when 
> you add a feature, you do that in a way that retrofit an existing 
> feature so the number of features stay more or less constant.
>
> I don't think that a partial statement is a bug. The rules i propose 
> make it more explicit by adding "default:" or "default -> {}" at the 
> end, but the semantics is still the same.
>
>
>         for 1/, it's about designing with the future in mind, if most
>         switch are switch on types, let have the right behavior
>
>
>     I think you lost me already, as I don't think it's the right
>     behavior.  Statements are partial. 
>
>
> Ok, here i should have use "right default" instead of "right 
> behavior", you are right that it's not about the behavior, my bad on 
> that.
>
>
>
>     (I probably shouldn't even mention that this creates a new "action
>     at a distance" problem since the totality semantics depend on the
>     operand type (see, I was on the debate team in high school too),
>     so I won't, because it would be unconstructive.)
>
>
> good you did not mention it because as far as i understand for null, 
> there is a difference between a switch on types and the already 
> existing switches.
>
>
>     But I will mention that the operand type isn't even the right
>     thing to key off of here, because even if we are switching on
>     strings, we might still want to use type patterns with guards:
>
>         switch (int) {
>             case 0: println("zero");
>             case 1: println("one");
>             case int x where x%2 == 0: println("even");
>         }
>
>     Is this an old switch, or a "type" switch?  Well, it can't be
>     expressed as an old switch, since it uses type patterns, but it is
>     a switch on old types.
>
>
> Good question,
> from the user POV it's either an error or a warning, so in both cases 
> it's a call for action, so for most user, using Alt+Enter or Ctrl+1 
> will fix the issue (insert a "default:")
> for us the EG or people writing compilers, it's a new switch because 
> you have a case that is using a pattern.
>
>       So should it be total? 
>
>
> If you get an error or a warning it's because it's not total.
>
>     I think the line where you want to cut is fuzzier than you think,
>     and that's going to confuse the heck out of users.
>
>
> The new switch will confuse a lot of users anyway, it's something i 
> have remarked when doing presentations about the pattern matching, you 
> have to explain the syntax because not enough Java devs have not been 
> exposed to pattern matching in an another languages before.
> So
>
>
>     So overall, while it's a fair question to ask "could we get away
>     with defining switch to always be total, carve out an exception
>     for all the existing idioms, and not confuse the users too much",
>     I think that would be taking it too far. 
>
>
> I think that retrofitting the old switch to a common behavior at the 
> same time you introduce the new construct is not too far, again as you 
> said during the development of the expression switch, it's far easier 
> to explain one behavior that to explain multiple (statement vs 
> expression switch with respect to totality) or to have to explain when 
> to use which kind of switch (switch vs sealed-switch).
>
> Rémi
>
>
>
>
>
>
>
>
>     On 8/31/2020 11:17 AM, Remi Forax wrote:
>
>
>
>         ------------------------------------------------------------------------
>
>             *De: *"Brian Goetz" <brian.goetz at oracle.com>
>             *À: *"amber-spec-experts"
>             <amber-spec-experts at openjdk.java.net>
>             *Envoyé: *Lundi 31 Août 2020 15:35:32
>             *Objet: *Re: [pattern-switch] Opting into totality
>
>             Totality is a term that language designers like, but may
>             not be all that evocative to users.  So switch-total might
>             not exactly turn on the light bulb for them.  In this
>             manner, “sealed” has a useful connotation that has nothing
>             to do with sealed types: non-leakiness: a sealed switch
>             doesn’t leak any unprocessed values!
>
>             Test driving ...
>
>                 sealed switch (x) { … }
>                 sealed-switch (x) { … }
>                 switch-sealed (x) { … }
>
>             “A switch may be sealed with the sealed modifier;
>             expression switches are implicitly sealed.  The set of
>             case patterns for a sealed switch must be total with some
>             remainder; synthetic throwing cases are inserted for the
>             remainder.”
>
>
>         Those are all "snitch" moves, let's avoid that because all you
>         said about having more than one kind of switch still apply.
>
>         Here are some facts that can help us,
>         - there is not a lot of existing switches in the wild
>         - as you said, there is a very good chance that the switch on
>         types become the dominant switch.
>
>         Now, divide and conquer,
>         1/ a switch on type (statement or expression) should always be
>         non leaky
>         2a/ add a warning on all existing leaky statement switches
>         forcing them to have a default if not exhaustive
>         2b/ for an exhaustive enum switch, add a warning if the switch
>         has a default.
>               and if there is no default, let the compiler add a
>         "default -> throw ICCE", it's a breaking change but it should
>         be ok because IDEs currently ask for a default in a switch on
>         enums.
>         explanations
>         for 1/, it's about designing with the future in mind, if most
>         switch are switch on types, let have the right behavior
>         for 2a/, ask users to fix leaky statement switches, even if we
>         introduce a selaed-switch, we will need this warning to
>         gradually move to a better world.
>         for 2b/, ask users to fix exhaustive enum switches so it works
>         like a switch on type.
>
>         I may be wrong with the idea of adding a "default -> throw" on
>         enum switches without a default, it may break a lot of codes,
>         but i believe it worth the try.
>
>         And BTW, we should also emit a warning if the default is in
>         the middle of the switch, again to drive user to think in term
>         of switch on type constraints.
>
>         Rémi
>
>
>                 On Aug 31, 2020, at 9:25 AM, Brian Goetz
>                 <brian.goetz at oracle.com
>                 <mailto:brian.goetz at oracle.com>> wrote:
>
>                 I think this is the main open question at this point.
>
>                 We now have a deeper understanding of what this means,
>                 and the shape of the remainder.  Totality means not
>                 only “spot check me that I’m right”, but also “I know
>                 there might be some remainder, please deal with it.”  
>                 So totality is not merely about type checking, but
>                 about affirmative handling of the remainder.
>
>                 Expression switches automatically get  this treatment,
>                 and opting _out_ of that makes no sense for expression
>                 switches (expressions must be total), but statement
>                 switches make sense both ways (just like unbalanced
>                 and balanced if-else.)  Unfortunately the default has
>                 to be partial,  so the main question is, how  do we
>                 indicate the desire for totality in a way that is
>                 properly evocative for the user?
>
>                 We’ve talked about modifying switch (sealed switch), a
>                 hyphenated keyword (total-switch), a trailing modifier
>                 (switch case), and synthetic cases (“default:
>                 unreachable”).  Of course at this point it’s “just
>                 syntax”, but I think our goal should be picking
>                 something that  makes it obvious to users that what’s
>                 going on is not merely an assertion of totality, but
>                 also a desire to handle the remainder.
>
>                      - How does a switch opt into totality, other than
>                     by being an expression switch?
>
>
>
>
>

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://mail.openjdk.java.net/pipermail/amber-spec-experts/attachments/20200831/fe55b967/attachment-0001.htm>


More information about the amber-spec-experts mailing list