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

Brian Goetz brian.goetz at oracle.com
Thu Jan 26 14:36:22 UTC 2023


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

On 1/26/2023 9:25 AM, forax at univ-mlv.fr wrote:
>
>
> ------------------------------------------------------------------------
>
>     *From: *"Angelos Bimpoudis" <angelos.bimpoudis at oracle.com>
>     *To: *"Remi Forax" <forax at univ-mlv.fr>
>     *Cc: *"amber-spec-experts" <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).
>
>
>     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 <forax at univ-mlv.fr>
>     *Sent:* 26 January 2023 14:16
>     *To:* Angelos Bimpoudis <angelos.bimpoudis at oracle.com>
>     *Cc:* amber-spec-experts <amber-spec-experts at openjdk.org>
>     *Subject:* [External] : Re: Draft JEP on Primitive types in
>     patterns, instanceof, and switch
>     > From: "Angelos Bimpoudis" <angelos.bimpoudis at oracle.com>
>     > To: "amber-dev" <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
>
>     > "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$
>     ]
>
>     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/98a1ca99/attachment-0001.htm>


More information about the amber-spec-experts mailing list