<!DOCTYPE html><html><head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
</head>
<body><div style="font-family: sans-serif;"><div class="plaintext" style="white-space: normal;"><p dir="auto">If we make range-comparison a non-primitive, via some sort of user-programmable pattern mechanism, we lose exhaustiveness.</p>
<p dir="auto">But we’d simplify the language, since we’d be “growing a language” (Guy’s YouTube talk!) via library code, not via adding to the spec.  We’d get a switch like this:</p>
<blockquote style="margin: 0 0 5px; padding-left: 5px; border-left: 2px solid #777777; color: #777777;"><p dir="auto">switch (b)
<br>
   {</p>
<p dir="auto">case Range.of(-128, -1)  -> "It's negative!";
<br>
case 0         -> "It's zero!";
<br>
case Range.of(1, 127)    -> "It's positive!";</p>
<p dir="auto">   }</p>
</blockquote><p dir="auto">With that approach, the coder needs a concluding case to force exhaustiveness:</p>
<blockquote style="margin: 0 0 5px; padding-left: 5px; border-left: 2px solid #777777; color: #777777;"><p dir="auto">  … default ->  "It's positive!";</p>
</blockquote><p dir="auto">or even</p>
<blockquote style="margin: 0 0 5px; padding-left: 5px; border-left: 2px solid #777777; color: #777777;"><p dir="auto">  … default ->  throw AssertionError();</p>
</blockquote><p dir="auto">That makes the patterns a little less compositional than a hardwired feature, but otherwise it’s a solid tradeoff.</p>
<p dir="auto">Hmm, in principle, it would also be possible to encode ranges in Java’s type system, enough to make some switches like this be exhaustive.  (With the right library definitions.)  The C2 JIT type system, used for optimizations, is fully aware of integer and long subrange types.  (C2 doesn’t do types representing multiple unconnected ranges, as of today.)  That range-based type system, in fact, is how C2 would (after inlining) conclude that the above switch was in fact exhaustive.  C2 would not bother to compile an unreached path to throw the impossible exception.</p>
<p dir="auto">That is, the JIT would properly optimize the switch as exhaustive, even if the static analysis of javac couldn’t quite get the job done.  That’s a normal state of affairs:  The JIT always knows more online than javac does offline.</p>
<p dir="auto">To be clear:  I would never want to see ranges in the JLS (Java) type system.  (IMO the volume of details would be overwhelming, with tricky rules for each operator, and all that for not enough gain.)  Hence, if range patterns are user-defined, then exhaustiveness over ranged cases is probably something we have to leave off the table.  The JIT would fix it under the covers, but there would be some warts in the source code (the default cases above).</p>
<p dir="auto">On 13 Mar 2024, at 10:40, Brian Goetz wrote:</p>
</div><blockquote class="embedded" style="margin: 0 0 5px; padding-left: 5px; border-left: 2px solid #777777; color: #777777;"><div id="471F6180-8342-4423-BFC3-10D75B1FD67C">

<font size="4" face="monospace">As an added bonus, it becomes practical to get useful exhaustiveness checking for integral types larger than boolean, as this example with byte shows. </font><br>
<br>
<div class="moz-cite-prefix">On 3/13/2024 12:33 PM, David Alayachew wrote:<br></div>
<blockquote type="cite" cite="mid:CAA9v-_NWF_6x4OaQxGyRmOm7hXkEqL+8dK+7No7PaCabAJPDbw@mail.gmail.com">
<div dir="ltr">
<div class="gmail_default" style="font-family:monospace">Well, what Brian and RedIO are suggesting would be more like this.</div>
<div class="gmail_default" style="font-family:monospace"><br></div>
<div class="gmail_default" style="font-family:monospace">byte b = 123;<br></div>
<div class="gmail_default" style="font-family:monospace"><br></div>
<div class="gmail_default" style="font-family:monospace">System.out.println</div>
<div class="gmail_default" style="font-family:monospace">(</div>
<div class="gmail_default" style="font-family:monospace">   switch (b)</div>
<div class="gmail_default" style="font-family:monospace">   {</div>
<div class="gmail_default" style="font-family:monospace"><br></div>
<div class="gmail_default" style="font-family:monospace">      case -128..-1  -> "It's negative!";</div>
<div class="gmail_default" style="font-family:monospace">      case 0         -> "It's zero!";<br></div>
<div class="gmail_default" style="font-family:monospace">
<div class="gmail_default" style="font-family:monospace">      case 1..127    -> "It's positive!";</div>
</div>
<div class="gmail_default" style="font-family:monospace"><br></div>
<div class="gmail_default" style="font-family:monospace">   }</div>
<div class="gmail_default" style="font-family:monospace">)</div>
<div class="gmail_default" style="font-family:monospace">;<br></div>
<div class="gmail_default" style="font-family:monospace"><br></div>
<div class="gmail_default" style="font-family:monospace">The difference is, in this example, it would be EXHAUSTIVE, NO DEFAULT CLAUSE NECESSARY. Your example requires either a default or a type pattern to be exhaustive, as do basically all switches that use when clauses.</div>
<div class="gmail_default" style="font-family:monospace"><br></div>
<div class="gmail_default" style="font-family:monospace">That exhaustiveness is powerful because -- patterns compose. For example, if you have a complex set of number checks, this switch will tell you if you left a value out. That is the power of exhaustiveness. When you combine it with composition, you can take an arbitrarily complex domain, and the compiler will let you know if you missed a case.<br></div>
</div>
<br>
<div class="gmail_quote">
<div dir="ltr" class="gmail_attr">On Wed, Mar 13, 2024 at 12:13 PM Josiah Noel <<a href="mailto:josiahnoel@gmail.com" target="_blank" moz-do-not-send="true" class="moz-txt-link-freetext">josiahnoel@gmail.com</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 dir="ltr">
<div dir="ltr">
<div dir="ltr">
<div dir="ltr">
<div dir="ltr">we sorta have this with switch guards
<div><br></div>
<div>
<div style="background-color:rgb(28,31,34);padding:0px 0px 0px 2px">
<div style="color:rgb(199,205,209);font-family:Consolas;white-space:pre-wrap">
<p style="margin:0px"><span style="color:rgb(255,0,127)">switch</span> <span style="color:rgb(249,250,244)">(</span><span style="color:rgb(207,191,173)">intyMcIntFace</span><span style="color:rgb(249,250,244)">)</span> <span style="color:rgb(249,250,244)">{</span></p>
<p style="margin:0px"><span style="color:rgb(255,0,127)">case</span> <span style="color:rgb(82,227,246)">Integer</span> <span style="color:rgb(207,191,173)">i</span> <span style="color:rgb(197,104,28)">when</span> <span style="color:rgb(207,191,173)">i</span> <span style="color:rgb(255,0,127)">></span> <span style="color:rgb(196,140,255)">1</span> <span style="color:rgb(255,0,127)">&&</span> <span style="color:rgb(207,191,173)">i</span> <span style="color:rgb(255,0,127)"><</span> <span style="color:rgb(196,140,255)">10</span> <span style="color:rgb(255,0,127)">-></span> <span style="color:rgb(249,250,244)">{}</span></p>
<p style="margin:0px"></p>
<p style="margin:0px"><span style="color:rgb(255,0,127)">case</span> <span style="color:rgb(196,140,255)">42</span> <span style="color:rgb(255,0,127)">-></span> <span style="color:rgb(249,250,244)">{}</span></p>
<p style="margin:0px"></p>
<p style="margin:0px"><span style="color:rgb(255,0,127)">default</span> <span style="color:rgb(255,0,127)">-></span> <span style="color:rgb(255,0,127)">throw</span> <span style="color:rgb(255,0,127)">new</span> <span style="color:rgb(167,236,33)">IllegalArgumentException</span><span style="color:rgb(249,250,244)">(</span><span style="color:rgb(236,228,126)">"Unexpected value: "</span><span style="color:rgb(249,250,244)">)</span><span style="color:rgb(255,0,127)">;</span></p>
<p style="margin:0px"><span style="color:rgb(249,250,244)">}</span></p>
</div>
</div>
</div>
</div>
</div>
<input name="virtru-metadata" type="hidden" value="{"email-policy":{"disableCopyPaste":false,"disablePrint":false,"disableForwarding":false,"enableNoauth":false,"expandedWatermarking":false,"expires":false,"sms":false,"expirationNum":1,"expirationUnit":"days","isManaged":false,"persistentProtection":false},"attachments":{},"compose-id":"3","compose-window":{"secure":false}}"></div>
</div>
<br>
<div class="gmail_quote">
<div dir="ltr" class="gmail_attr">On Wed, Mar 13, 2024 at 8:16 AM Red IO <<a href="mailto:redio.development@gmail.com" target="_blank" moz-do-not-send="true" class="moz-txt-link-freetext">redio.development@gmail.com</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 dir="auto">The switch statement saw a huge transformation over the past few releases. So I was quite surprised to realize that the current switch construct can't check the range of an value.
<div dir="auto">Example case x is between y and z.</div>
<div dir="auto">I'm most likely not the first one to notice that. Is there any discussion about adding some sort of range pattern? Would fit in the notion of the switch checking patterns quite well. </div>
<div dir="auto"><br></div>
<div dir="auto">Great regards </div>
<div dir="auto">RedIODev </div>
</div>
</blockquote>
</div>
</div>
</blockquote>
</div>
</blockquote>
<br></div></blockquote>
<div class="plaintext" style="white-space: normal;">
</div>
</div></body>

</html>