<!DOCTYPE html><html><head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
</head>
<body>
<p>Note that "thread safe classes" (I'd want to be more precise in
wording and explicitly call it out as <b>synchronized classes</b>)
do not guarantee atomicity of access over 2+ accessors anyway, and
to be able to perform such accesses you'd both need to know that
the exact implementation is using synchronization for concurrency
control, AND you'll need to know exactly which lock/monitor to
obtain.</p>
<p>So that's a whole lot of internal implementation concern which
you need to deal with, and in that case, you can also decide to
synchronize on the instance <b>before/around</b> the match, and
you'll have your atomicity.</p>
<div class="moz-cite-prefix">On 2026-01-19 08:45, <a class="moz-txt-link-abbreviated" href="mailto:forax@univ-mlv.fr">forax@univ-mlv.fr</a>
wrote:<br>
</div>
<blockquote type="cite" cite="mid:1047076842.19723466.1768808741384.JavaMail.zimbra@univ-eiffel.fr">
<div style="font-family: arial, helvetica, sans-serif; font-size: 12pt; color: #000000">
<div><br>
</div>
<div><br>
</div>
<hr id="zwchr" data-marker="__DIVIDER__">
<div data-marker="__HEADERS__">
<blockquote style="border-left:2px solid #1010FF;margin-left:5px;padding-left:5px;color:#000;font-weight:normal;font-style:normal;text-decoration:none;font-family:Helvetica,Arial,sans-serif;font-size:12pt;"><b>From:
</b>"Viktor Klang" <a class="moz-txt-link-rfc2396E" href="mailto:viktor.klang@oracle.com"><viktor.klang@oracle.com></a><br>
<b>To: </b>"Brian Goetz" <a class="moz-txt-link-rfc2396E" href="mailto:brian.goetz@oracle.com"><brian.goetz@oracle.com></a>,
"Remi Forax" <a class="moz-txt-link-rfc2396E" href="mailto:forax@univ-mlv.fr"><forax@univ-mlv.fr></a><br>
<b>Cc: </b>"amber-spec-experts"
<a class="moz-txt-link-rfc2396E" href="mailto:amber-spec-experts@openjdk.java.net"><amber-spec-experts@openjdk.java.net></a><br>
<b>Sent: </b>Monday, January 19, 2026 1:08:05 AM<br>
<b>Subject: </b>Re: Data Oriented Programming, Beyond
Records<br>
</blockquote>
</div>
<div data-marker="__QUOTED_TEXT__">
<blockquote style="border-left:2px solid #1010FF;margin-left:5px;padding-left:5px;color:#000;font-weight:normal;font-style:normal;text-decoration:none;font-family:Helvetica,Arial,sans-serif;font-size:12pt;">
<p>Since someone said <b>synchronized</b>, I was summoned.</p>
</blockquote>
<div><br>
</div>
<div>:)</div>
<div><br data-mce-bogus="1">
</div>
<blockquote style="border-left:2px solid #1010FF;margin-left:5px;padding-left:5px;color:#000;font-weight:normal;font-style:normal;text-decoration:none;font-family:Helvetica,Arial,sans-serif;font-size:12pt;">
<p><br>
<br>
If a definition of deconstruction is isomorphic to an
instance-of check plus invoking N accessors, it is clear
that it would have the same atomicity as invoking the
accessors directly (i.e. none).</p>
<p>I would say that it is much more consistent, than to try
to create special-cases with different atomicity
guarantees. Also, there is nothing which prevents exposing
a "shapshot"-method which returns a record (or other
carrier class) if one wants atomicity in matching:<br>
<br>
switch (foo) {<br>
case Foo foo when foo.snapshot() instanceof
FooSnapshot(var x, var y) -><br>
}<br>
<br>
PS. it's worth noting that this only applies to types
which can enforce stable snapshotting, either via <b>synchronized</b>
or via optimistic concurrency control schemes such as STM.</p>
</blockquote>
<div><br>
</div>
<div>yes,</div>
<div>snapshoting is a good term to describe the semantics.</div>
<div><br data-mce-bogus="1">
</div>
<div>Conceptually, you do not want your object to change state
in the middle of the pattern matching, so you snapshot it.</div>
<div><br data-mce-bogus="1">
</div>
<div>For me, this is no different from having a value class to
guarantee atomicity by default, by default pattern matching
should guarantee that you can not see an object in a state
that does not exist. </div>
<div><br data-mce-bogus="1">
</div>
<div>I do not like the fact that a user has to call
.snapshot() explicitly because it goes against the idea that
in Java, a thread safe class is like any other class from
the user POV, the maintainer of the class has to do more
work, but from the user POV a thread safe class works like
any other classes.</div>
<div>Here you are asking the thread safe classes to have an
extra step at use site when using pattern matching.</div>
<div><br data-mce-bogus="1">
</div>
<div>That why i said that by not providing snapshoting by
default, it makes thread safe classes are not first class
objects anymore</div>
<div> see <a href="https://urldefense.com/v3/__https://en.wikipedia.org/wiki/First-class_citizen__;!!ACWV5N9M2RV99hQ!NN-Sp9RWODO8xckNcMktjEc6QIh40fY7xUZOQfrIF3CoHIV5R5Qk0vNmTfWgoOa4mrk_tmsjVuM173J9BgrG$" moz-do-not-send="true">https://en.wikipedia.org/wiki/First-class_citizen</a></div>
<div><br data-mce-bogus="1">
</div>
<div>regards,</div>
<div>Rémi</div>
<div><br data-mce-bogus="1">
</div>
<blockquote style="border-left:2px solid #1010FF;margin-left:5px;padding-left:5px;color:#000;font-weight:normal;font-style:normal;text-decoration:none;font-family:Helvetica,Arial,sans-serif;font-size:12pt;">
<div class="moz-cite-prefix">On 2026-01-18 17:57, Brian
Goetz wrote:<br>
</div>
<blockquote cite="mid:071138f8-ba07-465a-94be-3e51c2d91ffb@oracle.com">
You're trying to make a point, but you're walking all
around it and not making it directly, so I can only guess
at what you mean. I think your point is: "if you're going
to embrace mutability, you should also embrace
thread-safety" (but actually, I think you are really
trying to argue against mutability, but you didn't use any
of those words, so again, we're only guessing at what you
really mean.)<br>
<br>
A mutable carrier can be made thread-safe by protecting
the state with locks or volatile fields or delegation to
thread-safe containers, as your example shows. And since
pattern matching proceeds through accessors, it will get
the benefit of those mechanisms to get race-freedom for
free. But you want (I think ) more: that the dtor not
only retrieves the latest value of all the components, but
that it must be able to do so _atomically_. <br>
<br>
I think the case you are really appealing to is one where
there an invariant that constrains the state, such as a
mutable Range, because then if one observed a range
mid-update and unpacked the bounds, they could be seen to
be inconsistent. So let's take that: <br>
<br>
class Range(int lo, int hi) { <br>
private int lo, hi;<br>
<br>
Range { <br>
if (lo > hi) throw new IAE();<br>
}<br>
<br>
// accessors synchronized on known monitor, such
as `this`<br>
}<br>
<br>
Now, while a client will always see up-to-date values for
the range components (Range is race-free), the worry is
that they might see something _too_ up-to-date, which is
to say, seeing a range mid-update:<br>
<br>
case Range(var lo, var hi): <br>
<br>
while another thread does<br>
<br>
sync (monitor of range) { range.lo += 5; range.hi +=
5; }<br>
<br>
If the range is initially (0,1), with some bad timing, the
client could see lo=6, hi=1 get unpacked, and scratch
their heads about what happened. <br>
<br>
This is analogous to the case where we have an ArrayList
wrapped with a synchronizedList; while access to the
list's state is race-free, if you want a consistent
snapshot (such as iterating it), you have to hold the lock
for the duration of the composite operation. Similarly,
if you have a mutable carrier that might be concurrently
modified, and you care about seeing updates atomically,
you would have to hold the lock during the pattern match:<br>
<br>
sync (monitor of range) { Range(var lo, var hi) =
range; ... use lo/hi ... }<br>
<br>
I think the argument you are (not) making goes like this:<br>
<br>
- We will have no chance to get users to understand that
deconstruction is not atomic, because it just _looks_ so
atomic!<br>
- Therefore, we either have to find a way so it can be
made atomic, OR (I think your preference), outlaw mutable
carriers in the first place. <br>
<br>
(I really wish you would just say what you mean, rather
than making us guess and make your arguments for you...)<br>
<br>
While there's a valid argument there to make here (if you
actually made it), I'll just note that the leap from
"something bad and surprising can happen" to "so, this
design needs to be radically overhauled" is ... quite a
leap. <br>
<br>
(This is kind of the same leap you made about hash-based
collections: "there is a risk, therefore we must neuter
the feature so there are no risks." Rather than leaping
to "so let's change the design center", I would rather
have a conversation about what risks there _are_, and
whether they are acceptable, or whether the cure is worse
than the disease.)<br>
<br>
<br>
<br>
<br>
<br>
<div class="moz-cite-prefix">On 1/18/2026 7:49 AM, <a class="moz-txt-link-abbreviated moz-txt-link-freetext" href="mailto:forax@univ-mlv.fr" target="_blank" moz-do-not-send="true">forax@univ-mlv.fr</a> wrote:<br>
</div>
<blockquote cite="mid:1710737945.19433405.1768740540151.JavaMail.zimbra@univ-eiffel.fr">
<div style="font-family: arial, helvetica, sans-serif; font-size: 12pt; color: #000000">
<div><br>
</div>
<div><br>
</div>
<hr id="zwchr">
<div>
<blockquote style="border-left:2px solid #1010FF;margin-left:5px;padding-left:5px;color:#000;font-weight:normal;font-style:normal;text-decoration:none;font-family:Helvetica,Arial,sans-serif;font-size:12pt;"><b>From:
</b>"Brian Goetz" <a class="moz-txt-link-rfc2396E" href="mailto:brian.goetz@oracle.com" target="_blank" moz-do-not-send="true"><brian.goetz@oracle.com></a><br>
<b>To: </b>"Remi Forax" <a class="moz-txt-link-rfc2396E" href="mailto:forax@univ-mlv.fr" target="_blank" moz-do-not-send="true"><forax@univ-mlv.fr></a>,
"Viktor Klang" <a class="moz-txt-link-rfc2396E" href="mailto:viktor.klang@oracle.com" target="_blank" moz-do-not-send="true"><viktor.klang@oracle.com></a><br>
<b>Cc: </b>"amber-spec-experts" <a class="moz-txt-link-rfc2396E" href="mailto:amber-spec-experts@openjdk.java.net" target="_blank" moz-do-not-send="true"><amber-spec-experts@openjdk.java.net></a><br>
<b>Sent: </b>Sunday, January 18, 2026 2:00:19 AM<br>
<b>Subject: </b>Re: Data Oriented Programming,
Beyond Records<br>
</blockquote>
</div>
<div>
<blockquote style="border-left:2px solid #1010FF;margin-left:5px;padding-left:5px;color:#000;font-weight:normal;font-style:normal;text-decoration:none;font-family:Helvetica,Arial,sans-serif;font-size:12pt;"><font size="4" face="monospace">In reality, the
deconstructor is not a method at all. <br>
<br>
When we match:<br>
<br>
x instanceof R(P, Q)<br>
<br>
we first ask `instanceof R`, and if that
succeeds, we call the accessors for the first
two components. The accessors are instance
methods, but the deconstructor is not embodied
as a method. This is true for carriers as well
as for records.</font></blockquote>
<div><br>
</div>
<div>Pattern matching and late binding are dual only
for public types,</div>
<div>if an implementation class (the one containing
the fields) is not visible from outside, the way
to get to fields is by using late binding.</div>
<div><br>
</div>
<div>If the only way to do the late binding is by
using accessors, then you can not guarantee the
atomicity of the deconstruction,</div>
<div>or said differently the pattern matching will
be able to see states that does not exist.</div>
<div><br>
</div>
<div>Let say I have a public thread safe class
containing two fields, and I want see that class
has a carrier class,</div>
<div>with the idea that a carrier class either
provide a deconstructor method or accessors.</div>
<div>I can write the following code :</div>
<div><br>
</div>
<div> public final class ThreadSafeData(String
name, int age) {</div>
<div> private String name;</div>
<div> private int age;</div>
<div> private final Object lock = new Object();</div>
<div><br>
</div>
<div> public ThreadSafeData(String name, int age)
{</div>
<div> synchronized(lock) {
<div> this.name = name;</div>
<div> this.age = age;</div>
<div> } </div>
</div>
<div> }</div>
<div><br>
</div>
<div> public void set(String name, int age) {</div>
<div> synchronized(lock) {</div>
<div> this.name = name;</div>
<div> this.age = age;</div>
<div> }</div>
<div> }<br>
<br>
</div>
<div>
<div> public String toString() {</div>
<div> synchronized(lock) {</div>
<div> return name + " " + age;</div>
<div> }</div>
<div> }</div>
</div>
<div><br>
</div>
<div> public deconstructor() {. // no return
type, the compiler checks that the return values
have the same carrier definition</div>
<div> record Tuple(String name, int age) { }</div>
<div> synchronized(lock) {</div>
<div> return new Tuple(name, age);</div>
<div> }</div>
<div> }</div>
<div><br>
</div>
<div> // no accessors here, if you want to have
access the state, use pattern matching like this</div>
<div> // ThreadSafeHolder holder = ...</div>
<div> // ThreadSafeHolder(String name, int age)
= holder;</div>
<div> }</div>
<div> </div>
<div>I understand that you are trying to drastically
simplify the pattern matching model (yai !) by
removing the deconstructor method but by doing
that you are making thread safe classes second
class citizens. </div>
<div> </div>
<div>regards,</div>
<div>Rémi</div>
<div><br>
</div>
<blockquote style="border-left:2px solid #1010FF;margin-left:5px;padding-left:5px;color:#000;font-weight:normal;font-style:normal;text-decoration:none;font-family:Helvetica,Arial,sans-serif;font-size:12pt;"><font size="4" face="monospace"><br>
</font><br>
<div class="moz-cite-prefix">On 1/17/2026 5:09 PM,
<a class="moz-txt-link-abbreviated moz-txt-link-freetext" href="mailto:forax@univ-mlv.fr" target="_blank" moz-do-not-send="true">forax@univ-mlv.fr</a>
wrote:<br>
</div>
<blockquote cite="mid:1864311863.19305629.1768687793277.JavaMail.zimbra@univ-eiffel.fr">
<div style="font-family: arial, helvetica, sans-serif; font-size: 12pt; color: #000000">
<div><br>
</div>
<div><br>
</div>
<hr id="zwchr">
<div>
<blockquote style="border-left:2px solid #1010FF;margin-left:5px;padding-left:5px;color:#000;font-weight:normal;font-style:normal;text-decoration:none;font-family:Helvetica,Arial,sans-serif;font-size:12pt;"><b>From:
</b>"Viktor Klang" <a class="moz-txt-link-rfc2396E" href="mailto:viktor.klang@oracle.com" target="_blank" moz-do-not-send="true"><viktor.klang@oracle.com></a><br>
<b>To: </b>"Remi Forax" <a class="moz-txt-link-rfc2396E" href="mailto:forax@univ-mlv.fr" target="_blank" moz-do-not-send="true"><forax@univ-mlv.fr></a>,
"Brian Goetz" <a class="moz-txt-link-rfc2396E" href="mailto:brian.goetz@oracle.com" target="_blank" moz-do-not-send="true"><brian.goetz@oracle.com></a><br>
<b>Cc: </b>"amber-spec-experts" <a class="moz-txt-link-rfc2396E" href="mailto:amber-spec-experts@openjdk.java.net" target="_blank" moz-do-not-send="true"><amber-spec-experts@openjdk.java.net></a><br>
<b>Sent: </b>Saturday, January 17, 2026
5:00:41 PM<br>
<b>Subject: </b>Re: Data Oriented
Programming, Beyond Records<br>
</blockquote>
</div>
<div>
<blockquote style="border-left:2px solid #1010FF;margin-left:5px;padding-left:5px;color:#000;font-weight:normal;font-style:normal;text-decoration:none;font-family:Helvetica,Arial,sans-serif;font-size:12pt;">
<p>Just a quick note regarding the
following, given my experience in this
area:</p>
<div class="moz-cite-prefix">On 2026-01-17
11:36, Remi Forax wrote:<br>
</div>
<blockquote cite="mid:1085557496.17567763.1768646213005.JavaMail.zimbra@univ-eiffel.fr">A
de-constructor becomes an instance
method that must return a carrier
class/carrier interface, a type that has
the information to be destructured and
the structure has to match the one
defined by the type.</blockquote>
</blockquote>
<div><br>
</div>
<div>Hello Viktor,</div>
<div>thanks to bring back that point,</div>
<div><br>
</div>
<blockquote style="border-left:2px solid #1010FF;margin-left:5px;padding-left:5px;color:#000;font-weight:normal;font-style:normal;text-decoration:none;font-family:Helvetica,Arial,sans-serif;font-size:12pt;">
This simply <b>does not work</b> as a
deconstructor cannot be an instance-method
just like a constructor cannot be an
instance method: It strictly belongs to
the type itself (not the hierarchy) and</blockquote>
<div><br>
</div>
<div>It can work as you said for a concrete
type, but for an abstract type, you need
to go from the abstract definition to the
concrete one,</div>
<div>if you do not want to re-invent the
wheel here, the deconstructor has to be an
abstract instance method.</div>
<div><br>
</div>
<div>For example, with a non-public named
implementation</div>
<div><br>
</div>
<div>interface Pair<F, S>(F first, S
second) {</div>
<div> public <F,S> Pair<F,S>
of(F first, S second) {</div>
<div> record Impl<F, S>(F first, S
second) implements Pair<F, S>{ }</div>
<div> return new Impl<>(first,
second);</div>
<div> }</div>
<div>}</div>
<div><br>
</div>
<div>inside Pair, there is no concrete field
first and second, so you need a way to
extract them from the implementation.</div>
<div><br>
</div>
<div>This can be implemented either using
accessors (first() and second()) but you
have a problem if you want your
implementation to be mutable and
synchronized on a lock (because the
instance can be changed in between the
call to first() and the call to second())
or you can have one abstract method, the
deconstructor.</div>
<div><br>
</div>
<blockquote style="border-left:2px solid #1010FF;margin-left:5px;padding-left:5px;color:#000;font-weight:normal;font-style:normal;text-decoration:none;font-family:Helvetica,Arial,sans-serif;font-size:12pt;">
it doesn't play well with implementing
multiple interfaces (name clashing), and
interacts poorly with overload resolution
(instead of choosing most-specific, you
need to select a specific point in the
hierarchy to call the method). </blockquote>
<div><br>
</div>
<div>It depends on the compiler translation,
but if you limit yourself to one
destructor per class (the dual of the
canonical constructor), the deconstructor
can be desugared to one instance method
that takes nothing and return
java.lang.Object, so no name clash and no
problem of overloading (because
overloading is not allowed, you have to
use '_' at use site).</div>
<div><br>
</div>
<blockquote style="border-left:2px solid #1010FF;margin-left:5px;padding-left:5px;color:#000;font-weight:normal;font-style:normal;text-decoration:none;font-family:Helvetica,Arial,sans-serif;font-size:12pt;">
<pre class="moz-signature">--
Cheers,
√</pre>
</blockquote>
<div><br>
</div>
<div>regards,</div>
<div>Rémi</div>
<div><br>
</div>
<blockquote style="border-left:2px solid #1010FF;margin-left:5px;padding-left:5px;color:#000;font-weight:normal;font-style:normal;text-decoration:none;font-family:Helvetica,Arial,sans-serif;font-size:12pt;">
<pre class="moz-signature">Viktor Klang
Software Architect, Java Platform Group
Oracle</pre>
<br>
</blockquote>
</div>
</div>
</blockquote>
<br>
<br>
</blockquote>
</div>
</div>
</blockquote>
<br>
</blockquote>
<pre class="moz-signature">--
Cheers,
√
Viktor Klang
Software Architect, Java Platform Group
Oracle</pre>
<br>
</blockquote>
</div>
</div>
</blockquote>
<pre class="moz-signature" cols="72">--
Cheers,
√
Viktor Klang
Software Architect, Java Platform Group
Oracle</pre>
</body>
</html>