Comparing ranges with switch

David Alayachew davidalayachew at gmail.com
Thu Mar 14 02:00:51 UTC 2024


Hey John,

Thanks for speaking on this. Very disappointing to hear since javac being
able to tell you the switch is exhaustive without a default would be
incredibly useful, but understood.

I would like clarification on one part -- you said "with tricky rules for
each operator". I had assumed that range patterns were only for >= and <=
operators. Effectively the BETWEEN operator from ORACLE SQL.

Do range patterns carry more operators in mind?

On Wed, Mar 13, 2024 at 6:59 PM John Rose <john.r.rose at oracle.com> wrote:

> 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) {
>>
>> case Integer i when i > 1 && i < 10 -> {}
>>
>> case 42 -> {}
>>
>> default -> throw new IllegalArgumentException("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/9da52f03/attachment-0001.htm>


More information about the amber-dev mailing list