<!DOCTYPE html><html><head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
</head>
<body>
<font size="4" face="monospace">Indeed so. Some people are having a
hard time making the shift away from `instanceof` as being purely
a type query. And this is one of the costs of the decision we
made to "lump" vs "split" in the surface syntax when we added
patterns at all; we had a choice of picking a new keyword (e.g.,
"matches") or extending instanceof to support patterns. This
choice had pros and cons on both sides of the ledger, and having
made a choice, we now have to live with whatever cons that choice
had. (FTR I am completely convinced that this was the better
choice, but that doesn't make the cons go away.)<br>
<br>
In C#, they spelled their `instanceof` operator `is`, and in that
world, the "this is only about types" interpretation is less
entrenched, for purely syntactic reasons; both <br>
<br>
if (anObject is String)<br>
and <br>
if (aFloat is int)<br>
<br>
seems pretty natural. It will take some time for people to
reprogram this accidental association, but once they do, it won't
be a problem.<br>
<br>
</font><br>
<div class="moz-cite-prefix">On 9/12/2025 2:01 PM, Archie Cobbs
wrote:<br>
</div>
<blockquote type="cite" cite="mid:CANSoFxuK-rG-VaR4LXETSqCx1==Zhga9eyhDuK+VvmYk1N4stA@mail.gmail.com">
<div dir="ltr">
<div>This is just an aside (I agree with everything Brian has
said).</div>
<div><br>
</div>
<div>I think a lot of the "uncomfortableness" comes from a
simple mental model adjustment that needs to occur.</div>
<div><br>
</div>
<div>If "42 instanceof float" feels normal to you, then no
adjustment is needed. But I think for some people it feels
funny.</div>
<div><br>
</div>
<div>Why? Because those people tend to read "x instanceof Y" as
"the type of x is some subtype of Y".</div>
<div><br>
</div>
<div>Why is that a problem? Well, what is "the type of x"? For
reference types, there is the compiler type and the runtime
type, and instanceof is a way to ask about the runtime type of
something that the code only knows by its compile-time type.
So far, so good.</div>
<div><br>
</div>
<div>But with primitives, there is no distinction between
compiler type and runtime type. An "int" is always an ordered
sequence of 32 bits.</div>
<div><br>
</div>
<div>So applying the traditional understanding of "instanceof"
leads you to this: "42 instanceof float" is obviously false,
because the statement "int is some subtype of float" is false.</div>
<div><br>
</div>
<div>So, int is not a subtype of float - but some ints are
representable as floats. The latter property is what matters
here.</div>
<div><br>
</div>
<div>So perhaps when we talk about this feature, we should start
by first telling everyone to replace any notion they might
have that "x instanceof Y" means "type of x is some subtype of
Y" with "the value x is representable as a Y". After that, the
waters should become much smoother.</div>
<div><br>
</div>
<div>-Archie</div>
<div><br>
</div>
</div>
<br>
<div class="gmail_quote gmail_quote_container">
<div dir="ltr" class="gmail_attr">On Fri, Sep 12, 2025 at
12:31 PM Brian Goetz <<a href="mailto:brian.goetz@oracle.com" moz-do-not-send="true" class="moz-txt-link-freetext">brian.goetz@oracle.com</a>>
wrote:<br>
</div>
<blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
<div> <br>
<br>
<div>On 9/11/2025 11:55 AM, Brian Goetz wrote:<br>
</div>
<blockquote type="cite"><br>
I explicitly asked you to answer a question on the
semantics when these conversions were NOT involved before
we moved onto these, because I think you are conflating
two separate things, and in order to get past just
repeating "but...lossy!", we have to separate them. <br>
</blockquote>
<br>
<font size="4" face="monospace">I see Remi has lost interest
in this discussion, so I will play both parts of the
dialogue on his behalf now. <br>
<br>
<blockquote type="cite">Let's start with the easy ones: <br>
<br>
Object p = "foo"; // widen String to
Object <br>
Object q = Integer.valueOf(3) // widen Integer to
Object <br>
... <br>
if (p instanceof String s) { ... } // yes it is <br>
if (q instanceof String s) { ... } // no it isn't <br>
<br>
We can widen String and Integer to Object; we can safely
narrow p back to String, but we can't do so for q,
because it is "outside the range" of references to
String (which embeds in "references to Object".) Does
this make sense so far? <br>
</blockquote>
<br>
Remi: It has always been this way. <br>
<br>
<blockquote type="cite">OK, now let's do int and long. <br>
<br>
long small = 3 <br>
long big = Long.MAX_VALUE <br>
<br>
if (small instanceof int a) { ... } // yes, it is
<br>
if (big instanceof int b) { ... } // no, it
isn't <br>
<br>
What these questions are asking is: can I safely narrow
these longs to int, just like the above. In the first
case, I can -- just like with String and Object. In the
second, I can't -- just like with Integer and Object.
Do we agree these are the same?<br>
</blockquote>
<br>
Remi: Yes Socrates, I believe they are. <br>
<br>
<blockquote type="cite">OK, now let's do int and double. <br>
<br>
double zero = 0; <br>
double pi = 3.14d; <br>
<br>
if (zero instanceof int i) { ... } <br>
if (pi instanceof int i) { ... } <br>
<br>
Same thing! The first exactly encodes a number that is
representable in int (i.e., could have arisen from
widening an int to double), the latter does not. <br>
</blockquote>
<br>
Remi: It could be no other way, Socrates.<br>
<br>
But we can replace double with float in the previous
example, and nothing changes:<br>
<br>
<blockquote type="cite"><font size="4" face="monospace">
float zero = 0; <br>
float pi = 3.14f; <br>
<br>
if (zero instanceof int i) { ... } <br>
if (pi instanceof int i) { ... } <br>
</font></blockquote>
<br>
Here, we are asking a sound question: does the number
encoded in this `float` exactly represent an `int`. For
`zero`, the answer is "of course"; for `pi`, the answer is
"obviously not."<br>
<br>
Remi: Yes, Socrates, that is clearly evident.<br>
<br>
<br>
I'm now entering guessing territory here, but I'm pretty
sure I understand what's making you uncomfortable. But,
despite the clickbaity headline and misplaced claims of
wrongness, this really has nothing to do with pattern
matching at all! It has to do with the existing
regrettable treatment of some conversions (which we well
understood are problematic, and are working on), and the
fact that by its very duality, pattern matching _exposes_
the inconsistency that while most "implicit" conversions
(more precisely, those allowed in method and assignment
context) are required to be "safe", we allow several lossy
conversions in these contexts too (int <--> float,
long <--> float, long <--> double). (The
argument then makes the leap that "because this exposes a
seeming inconsistency, the new feature must be wrong, and
should be changed." But it is neither fair nor beneficial
to blame the son, who is actually doing it right, for the
sins of the fathers.) <br>
<br>
In other words, you see these two cases as somehow so
different that we should roll back several years of
progress just to avoid acknowledging the inconsistency:<br>
<br>
float f = 0;<br>
if (f instanceof int i) { ... }<br>
<br>
and<br>
<br>
float g = 200_000_007; // lossy <br>
if (g instanceof int i) { ... }<br>
<br>
because in the first case, we are merely "recovering" the
int-ness of something that was an int all along, but in
the second case, we are _throwing away_ some of the int
value and then trying to recover it, but without the
knowledge that a previous lossy operation happened. <br>
<br>
But blaming pattern matching is blaming the messenger.
Your beef is with the assignment to g, that we allow a
lossy assignment without at least an explicit cast. And
this does seem "inconsistent"! We generally go out of our
way to avoid lossy conversions in assignments and method
invocation (by allowing widening conversions but not
narrowing ones) -- except that the conversion int ->
float is considered (mystifyingly) a "widening
conversion." <br>
<br>
Except there's no mystery. This was a compromise made in
1995 borne of a desire for Java to not seem "too
surprising" to C programmers. So this conversion (and two
of its irresponsible friends) were characterized as
"widenings", when in fact they are not. <br>
<br>
If I could go back to 1995 and argue against this, I
would. But I can't do that. What I can do is to
acknowledge that this was a regrettable misuse of the term
widening, and not extrapolate from this behavior. Can we
change the language to disallow these conversions in
assignment and method context? Unlikely, that would break
way too much code. We can, though, clarify the
terminology in the JLS, and start to issue warnings for
these lossy implicit conversions, and instead encourage an
explicit cast to emphasize the "convert to float, dammit"
intentions of the programmer (which is what we plan to do,
we just haven't finalized this plan yet.) But again, this
has little to do with the proper semantics of pattern
matching; it is just that pattern matching is the mirror
that reveals the bad behavior of existing past mistakes
more clearly. It would be stupid to extrapolate this
mistake forward into pattern matching -- that would make
it both more confusing and more complicated. Instead, we
admit our past mistakes and improve the language as best
as we can. In this case, there was a pretty good answer
here, despite the legacy warts. <br>
<br>
Before I close this thread, I need to reiterate that just
because there is a seeming inconsistency, this is not
necessarily evidence that the _most recent move_ is a
mistake. So next time, if you see an inconsistency,
instead of thumping your shoe on the table and crying
"mistake! mistake!", you could ask these questions
instead:<br>
<br>
- This seems like an inconsistency, but is it really?<br>
- If this is an inconsistency, does that mean that one
case or the other is mistake? <br>
- If there is a mistake, can it be fixed? If not, should
we consider changing course to avoid confusion, or are we
better off living with a small inconsistency to get a
greater benefit?<br>
<br>
These are the kinds of questions that language designers
grapple with every day. <br>
<br>
<br>
</font> </div>
</blockquote>
</div>
<div><br clear="all">
</div>
<br>
<span class="gmail_signature_prefix">-- </span><br>
<div dir="ltr" class="gmail_signature">Archie L. Cobbs<br>
</div>
</blockquote>
<br>
</body>
</html>