Data Oriented Programming, Beyond Records

Robbe Pincket robbepincket at live.be
Thu Jan 15 01:28:42 UTC 2026


> We can take advantage of the simplification offered by there being _only_ the
> canonical deconstruction pattern, and allow uses of deconstruction patterns to
> supply nested patterns for any _prefix_ of the component list.  So for the
> evolved record R: 
>
>    case R(P1, P2)
>
> would be interpreted as:
>
>    case R(P1, P2, _, _)
>
> where `_` is the match-all pattern.  This means that one can compatibly evolve a
> record by only adding new components at the end, and adding a suitable
> constructor for compatibility with existing constructor invocations.

Hi Brian

Love the stuff, except this one. To me I would expect 

    case R(P1, P2)

to be equivalent to

    case R(P1, P2, DEFAULT_C, DEFAULT_D)

Now it does seem unlikely to me at the moment that we can figure out what DEFAULT_C
and DEFAULT_D are supposed to be. Even less so if they are not constants and depend
on other fields.


I also have a question about reconstructors. Given your `Point` and `Point3d`
example carrier classes, what would the following function do?

    Point yPlane(Point p) {
        return p with { y = 0;}
    }
    
    void main() {
        System.out.println(yPlane(Point3d(15, 23, 70)));
    }

Will this `with` expression always invoke the class inferred in the source code 
`Point` and print `Point(x=15, y=0)` or will it depend on the actual type at 
runtime `Point3d` and print `Point3d(x=15, y=0, z=70)`

Kind regards
Robbe Pincket


More information about the amber-spec-observers mailing list