<!DOCTYPE html><html><head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
</head>
<body>
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" href="mailto:forax@univ-mlv.fr">forax@univ-mlv.fr</a>
wrote:<br>
</div>
<blockquote type="cite" 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" 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>"Brian Goetz" <a class="moz-txt-link-rfc2396E" href="mailto:brian.goetz@oracle.com"><brian.goetz@oracle.com></a><br>
<b>To: </b>"Remi Forax" <a class="moz-txt-link-rfc2396E" href="mailto:forax@univ-mlv.fr"><forax@univ-mlv.fr></a>, "Viktor
Klang" <a class="moz-txt-link-rfc2396E" href="mailto:viktor.klang@oracle.com"><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"><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 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;"><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 data-mce-bogus="1">
</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 data-mce-bogus="1">
</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 data-mce-bogus="1">
</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 data-mce-bogus="1">
</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 data-mce-bogus="1">
</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 data-mce-bogus="1">
</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 data-mce-bogus="1">
</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 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;"><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>
</body>
</html>