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.

Reply via email to