> De: "Brian Goetz" <brian.go...@oracle.com> > À: "Remi Forax" <fo...@univ-mlv.fr> > Cc: "Guy Steele" <guy.ste...@oracle.com>, "John Rose" > <john.r.r...@oracle.com>, > "amber-spec-experts" <amber-spec-experts@openjdk.java.net> > Envoyé: Mercredi 12 Août 2020 16:29:50 > Objet: Re: Next up for patterns: type patterns in switch
>>> So, who is bothered by the fact that case #3 gets Box(null), and case #6 >>> gets >>> Bag(null)? Anyone? (And, if not, but you are bothered by the lack of >>> totality >>> on the true catch-alls, why not?) >> I'm bothered if the pattern are not declared as total > That's too bad, because there was a proposal that might work (`default` > enables > type checking for totality on switches) and now you want to escalate it to > something that "totally" does not work (`default` makes _patterns_ total.) >> and i believe Stephen Colebourne on amber-dev is proposing exactly the same >> rules. in fact, it's not exactly the same rules, because Stephen rules allows "case Foo foo" and "default Foo foo" in the same switch, while i think that "case Foo foo" should be flagged as an error if the pattern is total. > You should read my long explanation to Stephen over there. TL;DR: this is not > engaging with half of what pattern matching is really for, and so is coming to > the wrong answer. Totality needs to be a property of the pattern, not the > context -- otherwise, the same pattern in switch doesn't mean the same pattern > in instanceof, and each construct needs its own totality hacks. This is just > another bad variant; worse, in fact, that the "any x" proposal. I agree that totality should be a property of a pattern not of a case, like currently "default" does. As you said, using "any" is better because it's per pattern and not per case. Continuing with the "default" keyword even if we may come with a better keyword latter, we are back to what Guy was proposing, "case default var x" or inside a nested-pattern "case Box(default var x)", default being the keyword saying it's total thus allows null. > Having total patterns is very important; if I have: > record Bag<T>(T t) implements Container<T> { } > record DoubleBox<T>(InnerBox<T> x) implements Container<T> { } > record InnerBox<T>(T x) { } > and I do > switch (container) { > case DoubleBox(InnerBox(var x)): ... > } > the outer pattern is not total on Containers (doesn't match Bag), but the > inner > pattern is once we match DoubleBox. I want to match all DoubleBoxes, and > destructure their contents. If I try to wedge totality into patterns through > switch case modifiers, then (a) the totality is all or nothing, at all levels, > and (b) what do I do when I want to refactor that switch into a chain of > instanceof operations? Then there's no way to express the pattern I want! > Totality must be a property of the pattern, and then we can define > (orthogonally, please) how the patterns interact with the enclosing construct. Right, it should be switch (container) { case DoubleBox(InnerBox(default var x)): ... } > I think the mistake that is dragging you down the wrong road is the assumption > that pattern matching is always about conditionality. But destructuring is > just > as important as conditionality. Sometimes a pattern is total (on a given > type), > and sometimes its not, but in all cases it describes the same destructuring. > What was wrong with the "just use case var x" proposal is that it said "you > can't use destructuring when you're total, because a null might sneak along > for > the ride", which was just mean. I agree destructuring is just as important as conditionality and those two things should be orthogonal. But i still think having a keyword to signal that a pattern (not a case) is total is better than letting people guess. Rémi