<!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>