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