> From: "Brian Goetz" <brian.go...@oracle.com> > To: "Remi Forax" <fo...@univ-mlv.fr> > Cc: "Jim Laskey" <james.las...@oracle.com>, "amber-spec-experts" > <amber-spec-experts@openjdk.java.net> > Sent: Thursday, March 3, 2022 7:59:01 PM > Subject: Re: [External] : Re: Proposal: java.lang.runtime.Carrier
>>>> For the pattern matching, >>>> we also need a 'with' method, that return a method handle that takes a >>>> carrier >>>> and a value and return a new carrier with the component value updated. >>> It is not clear to me why we "need" this. Rather than jumping right to >>> "Here is >>> the solution", can you instead try to shine some light on the problem you >>> are >>> trying to solve? >> When you have nested record patterns, each of these patterns contribute to >> introduce bindings, so when executing the code of the pattern matching, the >> code that match a nested pattern needs to add values into the carrier object. >> Given that the Carrier API is non mutable, we need the equivalent of a >> functional setter, a wither. > I don't think we need to do this. > Recall what nested patterns means: if R(T t) is a record, and Q is a pattern > that is not total, then > x matches R(Q) > means > x matches R(T t) && t matches Q > So if we have > record R(S s) { } > record S(int a, int b) { } > then > case R(S(var a, var b)) > operates by matching the target to R, deconstructing with the R deconstructor, > which yields a carrier of shape (S). Then we further match the first component > of this carrier to the S deconstructor, which yields a carrier of shape (II). > No mutation needed. > Note that this unrolling can happen in one of two ways: > - The compiler just unrolls it doing plain vanilla compiler stuff > - A pattern runtime has a nesting combinator that takes a pattern description > for an outer and an inner pattern, which when evaluated with R and S, yields a > carrier of shape (R;S;II), the compiler evaluates this nesting combinator with > condy, and uses that to do the match. > Either way, we don't need to mutate or replace carriers. You want the same carrier for the whole pattern matching: - if you have a logical OR between patterns (not something in the current Java spec but Python, C# or clojure core.match have it so we may want to add an OR in the future) - if different cases starts with the same prefix of patterns, so you don't have to re-execute the de-constructors/pattern methods of the prefix several times It's like when you create a value type, you start with the default value with all the field initialized with their default value, and each time there is a new binding, you do the equivalent of a withfield. Rémi