Draft JEP on Primitive types in patterns, instanceof, and switch

forax at univ-mlv.fr forax at univ-mlv.fr
Thu Jan 26 14:54:44 UTC 2023


> From: "Brian Goetz" <brian.goetz at oracle.com>
> To: "Remi Forax" <forax at univ-mlv.fr>, "Angelos Bimpoudis"
> <angelos.bimpoudis at oracle.com>
> Cc: "amber-spec-experts" <amber-spec-experts at openjdk.org>
> Sent: Thursday, January 26, 2023 3:36:22 PM
> Subject: Re: Draft JEP on Primitive types in patterns, instanceof, and switch

> Everything about floating point is difficult and fiddly and resists a
> one-size-fits-all treatment. Joe recently did some work to characterize the
> various ways floats can be compared -- representational equivalence, bitwise
> equivalence, and the traditional `==`, and put these in the spec of
> Float/Double, so we would have a vocabulary to discuss them.

> The main differences between these treatments are the treatment of NaN and
> signed zeroes. (And for $REASONS, there are multiple NaN bit patterns.)

> Representational equality means "same number", where all NaN values are the
> same. Float::equals uses representational equality.

> Bitwise equality means "same bit pattern".

> The `==` operator says that 0 == -0 and that NaN is equal to nothing, not even
> itself.

> For comparing a variable to a constant, representational equality is the obvious
> interpretation; `case nnn` means "is it the number nnn". This allows you to say
> `case NaN` and `case -0` and get the right answer (all of these relations agree
> on what to do about 1.0).

> For Valhalla's `==`, which we've decided means "substitutible" or
> "indistinguishable from", then bitwise equality is the obvious answer. Its sad
> that these are all different, and each case requires getting experts in a room
> to hash it out, but that's life with floating point.

> Your claim about refactoring anomalies is not right; the refactoring you offer
> will work for your example which uses 3.14, because `==` agrees with r.e. at
> the "regular" floating point values. Where it will fail is for NaN, as `==` has
> its own weird opinions about NaN. But `== NaN` is intrinsically useless anyway,
> since it folds to false, and anyone who knows what NaN is already knows this
> (probably by having been bitten by it).
That why there is Double.isNaN(). 

The problem is that there are two semantics and it's not clear to me which one is the one the user want. 
The proposed semantics choose for the user, and use the representational equality. 

It works until it does not work, i.e. if the pattern matching is used in a computation for which the difference between 0 and -0 is important, by example in a division. 

Here we have the luxury to ask users to be explicit about the semantics they want, because pattern matching on floats/doubles will be rare, so not committing to a peculiar a semantics seems a better choice here. 

Rémi 

> On 1/26/2023 9:25 AM, [ mailto:forax at univ-mlv.fr | forax at univ-mlv.fr ] wrote:

>>> From: "Angelos Bimpoudis" [ mailto:angelos.bimpoudis at oracle.com |
>>> <angelos.bimpoudis at oracle.com> ]
>>> To: "Remi Forax" [ mailto:forax at univ-mlv.fr | <forax at univ-mlv.fr> ]
>>> Cc: "amber-spec-experts" [ mailto:amber-spec-experts at openjdk.org |
>>> <amber-spec-experts at openjdk.org> ]
>>> Sent: Thursday, January 26, 2023 2:55:31 PM
>>> Subject: Re: Draft JEP on Primitive types in patterns, instanceof, and switch

>>> Thanks for the quick reply.

>>> I think there is one important factor here. By quickly inspecting the issues in
>>> the links, IIUC, the semantics of floating-point constants there follow the
>>> semantics of == ​. So -0 and 0 compare equal there (e.g., [
>>> https://github.com/rust-lang/rust/issues/41620#issuecomment-300587182 |
>>> https://github.com/rust-lang/rust/issues/41620#issuecomment-300587182 ] ).

>>> The JEP follows the road of "representation equivalence" as described in [
>>> https://download.java.net/java/early_access/jdk20/docs/api/java.base/java/lang/Double.html#fpNumericalEq
>>> |
>>> https://download.java.net/java/early_access/jdk20/docs/api/java.base/java/lang/Double.html#fpNumericalEq
>>> ]

>> In terms of semantics Double::equals may be better than double == double, this
>> seems to be the direction that Java is choosing (Valhhalla also used
>> Double::equals for value types containing a double).

>> But it means that introducing a "when" is not a valid refactoring
>> case double 3.14 -> ...
>> can not be refactored to
>> case double x when x == 3.14 -> ...

>> Most of my students thinks in terms of equivalence, breaking this kind of
>> refactoring make the proposed semantics not intuitive.

>> That's why i think it's better to not allow double/float constants, so people
>> have to be explicit about the semantics they want.

>> regards,
>> Rémi

>>> From: Remi Forax [ mailto:forax at univ-mlv.fr | <forax at univ-mlv.fr> ]
>>> Sent: 26 January 2023 14:16
>>> To: Angelos Bimpoudis [ mailto:angelos.bimpoudis at oracle.com |
>>> <angelos.bimpoudis at oracle.com> ]
>>> Cc: amber-spec-experts [ mailto:amber-spec-experts at openjdk.org |
>>> <amber-spec-experts at openjdk.org> ]
>>> Subject: [External] : Re: Draft JEP on Primitive types in patterns, instanceof,
>>> and switch
>>>> From: "Angelos Bimpoudis" [ mailto:angelos.bimpoudis at oracle.com |
>>> > <angelos.bimpoudis at oracle.com> ]
>>> > To: "amber-dev" [ mailto:amber-dev at openjdk.org | <amber-dev at openjdk.org> ]
>>> > Sent: Thursday, January 26, 2023 10:48:47 AM
>>> > Subject: Draft JEP on Primitive types in patterns, instanceof, and switch

>>> > Hello all,

>>> > I would like to share this draft JEP with you about primitive types in patterns,
>>> > instanceof, and switch:

>>> > [ https://openjdk.org/jeps/8288476 | https://openjdk.org/jeps/8288476 ]

>>> > "Enhance pattern matching by allowing primitive types to appear anywhere in
>>> > patterns. Extend instanceof to support primitive types, and extend switch to
>>> > allow primitive constants as case labels."

>>> > Comments very much welcomed!

>>> > Many thanks,
>>> > Angelos

>>> I still think that the semantics proposed for pattern matching on primitive
>>> types is useless complexity with the perverse side effect of normalizing the
>>> usage of "default" in pattern matching (too many examples of this JEP are using
>>> "default") but we already discussed that.

>>> Allowing switching on double and float constants is just wrong.
>>> Rust is actually trying to remove that feature
>>> [ [
>>> https://urldefense.com/v3/__https://github.com/rust-lang/rust/issues/41255__;!!ACWV5N9M2RV99hQ!NfJ7KspB447oMGi0NoEyXC6s_w3vD1N-SBu5hiD4kMVAkmwDWPNbymH83iOnrkakPoayD6vwGwuB5NvedJfjH9LU$
>>> |
>>> https://urldefense.com/v3/__https://github.com/rust-lang/rust/issues/41255__;!!ACWV5N9M2RV99hQ!NfJ7KspB447oMGi0NoEyXC6s_w3vD1N-SBu5hiD4kMVAkmwDWPNbymH83iOnrkakPoayD6vwGwuB5NvedJfjH9LU$
>>> ] | [
>>> https://urldefense.com/v3/__https://github.com/rust-lang/rust/issues/41255__;!!ACWV5N9M2RV99hQ!NfJ7KspB447oMGi0NoEyXC6s_w3vD1N-SBu5hiD4kMVAkmwDWPNbymH83iOnrkakPoayD6vwGwuB5NvedJfjH9LU$
>>> |
>>> https://urldefense.com/v3/__https://github.com/rust-lang/rust/issues/41255__;!!ACWV5N9M2RV99hQ!NfJ7KspB447oMGi0NoEyXC6s_w3vD1N-SBu5hiD4kMVAkmwDWPNbymH83iOnrkakPoayD6vwGwuB5NvedJfjH9LU$
>>> ] ]

>>> I see no point to make the same mistake.

>>> Otherwise, the rest is fine.

>>> Rémi
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://mail.openjdk.org/pipermail/amber-spec-experts/attachments/20230126/1c45a2e0/attachment-0001.htm>


More information about the amber-spec-experts mailing list