----- Original Message -----
> From: "Brian Goetz" <brian.go...@oracle.com>
> To: "Remi Forax" <fo...@univ-mlv.fr>
> Cc: "amber-spec-experts" <amber-spec-expe...@openjdk.java.net>
> Sent: Wednesday, September 10, 2025 5:02:46 PM
> Subject: Re: Primitive type pattern (as actually specified) is considered 
> harmful

>> - you define "safe" as the revert operation on something which can be
>> lossy (my brain can not compute that),
> 
> Sorry about your brain, but I think this is straightforward.  Given sets
> A and B, with a pair of functions
> 
>     f: A -> B
>     g: B -> A
> 
> we can discuss properties of the composite functions `f . g` and `g .
> f`, and there are useful algebraic structures we can appeal to
> (isomorphisms, embedding-projection pairs, etc) that can characterize
> their behavior.  For example, A and B are isomorphic if `f . g == id_B`
> and `g . f == id_A`.
> 
> Type pairs like A=int and B=long form _embedding projection pairs_,
> where `g . f` is an identity function on A, and `f . g` is a
> well-behaved _approximation_ of the identity function on B (there's a
> more rigorous definition, but let's just call it "potentially lossy in a
> stable way", so that repeated application of f and g converges to an
> identity after the first loss.)  With the exception of the "weird"
> widening conversions that we borrowed too liberally from C, which are
> called "widening" but aren't, conversions pairs that are described as
> widening/narrowing pairs in JLS 5 have this property: int/long,
> int/double, float/double, String/Object, etc.
> 
> But it is really simple: c instanceof P iff the value of c is exactly
> representable in type P.
> 
> It might be tempting to say "if I can cast and cast back and get the
> same answer", but unfortunately that doesn't work, because there are
> lossy conversions whose inverse is also lossy in an exactly compensating
> way.  _This_ would be confusing.

As you said, there is a problem with the lossy conversions, and i'm confused 
why you want to be able to invert them given that you can not.
if you prefer, float instanceof int make little sense given that the widening 
conversion from int to float is lossy.

It's the same thing as with an unsafe cast, o instanceof List<String> make 
little sense, because converting List<String> to Object is lossy.


> 
>> - it does not work well with Valhalla, especially with the phase 3
>> (i.e. let's pretend that a primitive type is a value type) *
> 
> As I said, I think this is a distraction, but if you disagree, you are
> going to need to provide a much more exhaustive description of how you
> think Valhalla will work and why this is a conflict, than just appealing
> to claims like "won't work with Valhalla."   Or, alternately, if you
> want to focus entirely on that, then that's fine, start a new thread
> (but I would expect that mail to have more "how would X work" questions
> rather than assertions about how it would work.)


With Valhalla, Integer is seen as int | null, with Integer! being an equivalent 
of int.
Sadly Integer! is not int because Integer! is a subtype of Object while int is 
not,
but we can try to provide an integration that brush that as a detail.

So for the pattern matching, it would be sad if int and Integer! behave 
differently know that we know that we want to try to retrofit the primitive 
type to be value type.

The problem with the semantics you propose is that the behavior of a switch on 
an int and the switch on an Integer! is wildly different.
By example,

 switch(v) {
   case byte b -> ...
   case int i -> ...
 }

if v is an int the switch compiles, or if v is an Integer (or a Integer! when 
we will get them) the switch does not compile.


> 
>> - your interpretation is surprising when i've tried to explain it to
>> others people (even to people coming to JUGs).
> 
> I believe that, but as an educator, you should well know that often
> "surprise" is not an indication of "wrong theory" but "wrong user mental
> model", which implies that what is needed is more education. If we
> consistently designed the language for least-surprise, we would very
> quickly find ourselves in a pit where we cannot add anything, both
> because something always surprises a 1995-era programmer, and because we
> would have added layers and layers of ad-hoc "what we think the user
> expects" features that we would eventually collapse under our own
> weight.  (The "implicit conversion from float to int" is an example of
> this kind of mistake, and look where that got us.)

The problem is the inverse here, people welcome the change, the ability to use 
primitive types as a pattern,
the problem is that the behaviors is different from what people expects.

So it may make sense to have patterns that behave the way the JEP describe, but 
as pattern methods and not as type pattern.

regards,
Rémi

Reply via email to