Comparing ranges with switch

John Rose john.r.rose at oracle.com
Wed Mar 13 22:59:31 UTC 2024


If we make range-comparison a non-primitive, via some sort of 
user-programmable pattern mechanism, we lose exhaustiveness.

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:

> switch (b)
>    {
>
> case Range.of(-128, -1)  -> "It's negative!";
> case 0         -> "It's zero!";
> case Range.of(1, 127)    -> "It's positive!";
>
>    }

With that approach, the coder needs a concluding case to force 
exhaustiveness:

>   … default ->  "It's positive!";

or even

>   … default ->  throw AssertionError();

That makes the patterns a little less compositional than a hardwired 
feature, but otherwise it’s a solid tradeoff.

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.

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.

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).

On 13 Mar 2024, at 10:40, Brian Goetz wrote:

> As an added bonus, it becomes practical to get useful exhaustiveness 
> checking for integral types larger than boolean, as this example with 
> byte shows.
>
> On 3/13/2024 12:33 PM, David Alayachew wrote:
>> Well, what Brian and RedIO are suggesting would be more like this.
>>
>> byte b = 123;
>>
>> System.out.println
>> (
>> switch (b)
>>    {
>>
>> case -128..-1  -> "It's negative!";
>> case 0         -> "It's zero!";
>> case 1..127    -> "It's positive!";
>>
>>    }
>> )
>> ;
>>
>> 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.
>>
>> 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.
>>
>> On Wed, Mar 13, 2024 at 12:13 PM Josiah Noel <josiahnoel at gmail.com> 
>> wrote:
>>
>>     we sorta have this with switch guards
>>
>>     switch(intyMcIntFace){
>>
>>     caseIntegeri wheni >1&&i <10->{}
>>
>>     case42->{}
>>
>>     default->thrownewIllegalArgumentException("Unexpected value: ");
>>
>>     }
>>
>>
>>     On Wed, Mar 13, 2024 at 8:16 AM Red IO
>>     <redio.development at gmail.com> wrote:
>>
>>         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.
>>         Example case x is between y and z.
>>         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.
>>
>>         Great regards
>>         RedIODev
>>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://mail.openjdk.org/pipermail/amber-dev/attachments/20240313/d987e01b/attachment.htm>


More information about the amber-dev mailing list