<div dir="ltr"><div dir="ltr"><div class="gmail_default" style="font-size:small"><div class="gmail_default">Thank you for the explanation. True, separating the data and the data processing into different classes makes it more important to know about the changes. A compile time error or a warning can show you the changes. But using the default clause will eliminate this help. I can imagine an IDE check, which shows you the uncovered cases, in spite there's a default clause. But the best practice would be listing all the known types you are aware of but for some reason don't want to process or can't accept. (Hopefully using a concise syntax in the future.)<br><br>I still think so, forcing the totality of switch statements will result in a lot of default clauses, which eliminates the totality check, and makes some switches one line longer unnecessarily. But maybe I am wrong, and it will help the developers to think about the pros and cons of this situation and will result in better practices.</div><div class="gmail_default"><br></div><div class="gmail_default">Regards,</div><div class="gmail_default">Hunor</div></div></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Mon, 20 Jun 2022 at 15:26, Remi Forax <<a href="mailto:forax@univ-mlv.fr">forax@univ-mlv.fr</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div><div id="gmail-m_2669572480459463855zimbraEditorContainer" style="font-family:arial,helvetica,sans-serif;font-size:12pt;color:rgb(0,0,0)"><div>Wow, one day to deliver an email, that's not fast :)</div><div>I suppose it was stuck somewhere.<br></div><div><br></div><div>Rémi<br></div><div><br></div><div><blockquote style="border-left:2px solid rgb(16,16,255);margin-left:5px;padding-left:5px;color:rgb(0,0,0);font-weight:normal;font-style:normal;text-decoration:none;font-family:Helvetica,Arial,sans-serif;font-size:12pt"><div style="font-family:arial,helvetica,sans-serif;font-size:12pt;color:rgb(0,0,0)"><br><br><hr id="gmail-m_2669572480459463855zwchr"><div><blockquote style="border-left:2px solid rgb(16,16,255);margin-left:5px;padding-left:5px;color:rgb(0,0,0);font-weight:normal;font-style:normal;text-decoration:none;font-family:Helvetica,Arial,sans-serif;font-size:12pt"><b>From: </b>"Hunor Szegi" <<a href="mailto:hunor.szegi@gmail.com" target="_blank">hunor.szegi@gmail.com</a>><br><b>To: </b><a href="mailto:amber-dev@openjdk.org" target="_blank">amber-dev@openjdk.org</a><br><b>Sent: </b>Sunday, June 19, 2022 12:42:12 AM<br><b>Subject: </b>Totality at switch statements</blockquote><br><div>Hi Hunor,<br></div><div>thanks for your feedback.<br></div><br><div>Let's start to understand why we want pattern matching, until now, if you want to describe an algorithm on a recursive data structure, you put the data and the parts of the algorithm in the same place ; you declare an interface with an abstract method corresponding to the algorithm and you implement the interface with different classes/records.<br></div><div>In that case, the code of the algorithm is as important as the data, they are intermingled.<br></div><br><div>Now, we want to introduce pattern matching, the idea of the pattern matching is to separate the data from the algorithm, the data are still defined using an interface and records, but the algorithm is not defined as an abstract method of the interface but as a method outside the data definition. You may ask why doing that, it's because the definition of the data is more important than the algorithm itself. Unlike with an abstract method which tied the data and the algorithm, here the data structure more important than the code itself.<br></div><br><div>We have decided to express the pattern matching using switch, this means retrofitting the switch this new purpose.<br></div><div>We have done that in several moves, first fix the semantics inherited from the C by adding the arrow syntax, then extends the semantics to allow switch expression and add patterns on types (type pattern and record patterns). All these moves as to be backward compatible so switch statement on int, String and enum must be still work as before.</div><br><div>Totality is essential for pattern matching, it's the way to detect discrepancies between the definition of the data and the code of the pattern matching itself. Unlike with an abstract method, with pattern matching the data and the algorithm are defined in two different places so the data can be updated without the switch being updated. We want the compiler to fail in that case.</div><div>So all the new switch constructs (switch on null, switch with guards, switch on patterns, switch expression) fails if the switch is not total, detecting when the data and the switch are not aligned anymore.<br></div><br><div>This means that using "default" is now a blunder because while it makes the switch total it disable the compiler to warn the user when the data change.<br></div><div>In the details, it's not fully true because we can switch on an infinity of values (or on a range big enough that it's like infinity in practice) so we can not enumerate all possibles combinations.<br></div><div>Switches on ints and strings are in this category, so for them, there is no other solution than having a default. In the future a warning may be a good idea to ask for a default at the end of the switch.<br></div><div>For the switch on enum, a user can enumerate all the cases but because of backward compatibility, we need a backward compatible way to opt-in to totality, my preferred way to do that is to add a "case null -> throw null", which transforms the old switch on an enum to a new switch on an enum which asks for totality. <br></div><br><div>Now, to answer your questions, yes we want totality even in a switch statement to detect when the data change, default is kind of an anti-pattern so i don't see the need to have a special syntax for default -> {}, i prefer to keep the lambda syntax and the switch syntax aligned. Forcing totality on arrow syntax is something we have debated and we believe it's better to separate the two concerns: fix the semantics inherited from the C and totality, among other things it allows automatic conversion by tools between the colon syntax to the arrow syntax. Anyway, given that the arrow syntax is not a preview anymore, this option is not on the table anymore. About @total, you can use "case null -> throw null" instead. We may come with a true syntax later but not using an annotation because we have this rule that an annotation can not changed the semantics of the language.<br></div><br><div>I hope this helps to understand why we wan totality,<br></div><div>regards,<br></div><div>Rémi<br></div><br><blockquote style="border-left:2px solid rgb(16,16,255);margin-left:5px;padding-left:5px;color:rgb(0,0,0);font-weight:normal;font-style:normal;text-decoration:none;font-family:Helvetica,Arial,sans-serif;font-size:12pt"><br></blockquote></div><div><blockquote style="border-left:2px solid rgb(16,16,255);margin-left:5px;padding-left:5px;color:rgb(0,0,0);font-weight:normal;font-style:normal;text-decoration:none;font-family:Helvetica,Arial,sans-serif;font-size:12pt"><div dir="ltr"><div style="font-size:small">Hi All,</div><div style="font-size:small"><br></div><div style="font-size:small">I really like the progress of adding pattern matching to Java (and a lot of other features). I can not wait to use it in productive code (non-preview). But I would like to give you feedback about a tiny detail, about the totality of switch statements.</div><div style="font-size:small"><br></div><div style="font-size:small">Surely, the totality is necessary at switch expressions, but forcing it at a statement is questionable.</div><div style="font-size:small"><br></div><div style="font-size:small">It can be helpful for the programmers to check the totality in those cases when the intent is that. But it is quite common to create a switch statement that doesn't handle all of the possibilities. Why would it be different using patterns? Why is it beneficial to force totality? This check can be an IDE feature. (Or the programmer can try adding a default clause, and the duplicated totality will be shown as an error. But I know it isn't convenient.)</div><div style="font-size:small"><br></div><div style="font-size:small">Honestly I feel that the rule, when the totality is forced, is dictated simply by the necessity of backward compatibility. What will happen if a new type (for example double) will be allowed for the selector expression? The backward compatibility wouldn't be an issue, but it would be weird behaving differently with an int compared to a double, so I guess the totality won't be forced. What would happen if the finality requirement was removed, and the equality could be checked for all types? What about the totality check in this imagined future?</div><div style="font-size:small"><br></div><div style="font-size:small">Of course the best would be to allow the totality check somehow if the intent is that. A warning could be a solution, but that can be annoying. It will force the programmers to suppress it, or to add a default clause (what is the current solution). Adding a default clause could be treated as marking the intent: we don't want totality. But the actual syntax does not represent it clearly.<br></div><div style="font-size:small"><br></div><div style="font-size:small">Additionally, there are issues with the "empty" default clause. In the JEP the "default: break;" was recommended, but interestingly it doesn't work with the arrow syntax. ("default -> break;" is a compile time error, only the "default: {break;}" is possible.) We can use both the "default: {}" and "default -> {}", which is fine. But while the "default:" is possible (without body), the "default ->" is an error. I don't know what is the reason behind it. Allowing an empty body with the arrow syntax would make the actual solution a little bit cleaner.</div><div style="font-size:small"><br></div><div style="font-size:small">I think forcing the totality at statements is partly an intent for uniformity. The best would be if the same rules were applied to all cases, regardless if it is a statement or expression, old or arrow syntax. But backward compatibility can't allow full uniformity, it moves the separation into the middle of a box, instead of a clear distinction between a statement and expression. It creates more cases.</div><div style="font-size:small"><br></div><div style="font-size:small">It would be possible, forcing the totality only at the arrow syntax. But that would move some of the programmers using the old syntax, which may be less fortunate.</div><div style="font-size:small"><br></div><div style="font-size:small">It would be possible to allow the programmer to mark the intended totality. Maybe a new keyword would be too much for this purpose. Alternatively I can imagine allowing annotations at a switch statement/expression in the future. For example:</div><div style="font-size:small"><br></div><div style="font-size:small">@total</div><div style="font-size:small">switch (x) {</div><div style="font-size:small">...</div><div style="font-size:small">}</div><div style="font-size:small"><br></div><div style="font-size:small">If this syntax isn't possible, the annotation could be added right before the opening curly bracket. Alternatively a warning suppress annotation could be used specifically for the switch.</div><div style="font-size:small">But this is only a brainstorming. My main point is that I don't think the totality should be forced at switch statements. Or it should cause only a warning.</div><div style="font-size:small"><br></div><div style="font-size:small">I hope my feedback isn't pointless. <span style="color:rgb(0,0,0);white-space:pre-wrap">I'd be very interested to hear other people's opinions.</span></div><div style="font-size:small"><span style="color:rgb(0,0,0);white-space:pre-wrap"><br></span></div><div style="font-size:small"><span style="color:rgb(0,0,0);white-space:pre-wrap">Thank you in advance,</span></div><div style="font-size:small"><br></div><div style="font-size:small">Regards,</div><div style="font-size:small">Hunor </div></div></blockquote></div></div><br></blockquote></div></div></div></blockquote></div></div>