- Extension.  The proposal outlines a notion of abstract record,
    which provides a "width subtyped" hierarchy.  Some have questioned
    whether this carries its weight, especially given how Scala
    doesn't support case-to-case extension (some see this as a bug,
    others as an existence proof.)  Records can implement interfaces.


I also suggest we avoid abstract records. A reference to one may seem like a proper record but it will behave badly with regard to equals(). I don't see the upside compared to a common interface, and then you don't have to have the novel parameterized extends clause.

The hackneyed example: consider the below as a subset of a typical "model an expression with a tree" hierarchy.  Of course, a real hierarchy would have a lot more classes.

    sealed interface Node;
    record ValNode(int value) extends Node;
    record VarNode(String name) extends Node;
    abstract record BinOpNode(Node left, Node right) extends Node;
    record PlusNode(Node left, Node right) extends BinOpNode(left, right);
    record MulNode(Node left, Node right) extends BinOpNode(left, right);

Obviously there might be some common behavior for binary operation nodes that can be factored up into BinOpNode.  But also, there are times when matching against the abstract type makes sense too.  For example, if you want to traverse the tree and perform structural operations (say, detect if a tree contains a reference to the variable "x"), matching on abstract records is pretty useful:

    boolean containsVar(Node node, String name) {
        return switch (node) {
            case VarNode(String s) -> s.equals(name);
            case BinOpNode(var left, var right) -> containsVar(left, name) || containsVar(right, name);
            default -> false;
        }
    }

A client who is only interested in structural properties can match once on the abstract type, instead of matching explicitly on N effectively identical cases (and add more every time the hierarchy changes.)


On the other hand. As much as I want everyone to stick to immutable records as much as possible, it seems very costly to me to have to introduce a new keyword for "not final", and have users keep track of which things have which defaults. Let this just be "best practice", like it already is for regular fields (make them final unless you have good reason not to).

Pretend we already had non-final.  Does that change your inclination?  (When we do sealed types, we're likely going to need a way to say non-sealed anyway.)


     - Accessors.  Perhaps the most controversial aspect is that
    records are inherently transparent to read; if something wants to
    truly encapsulate state, it's not a record. Records will
    eventually have pattern deconstructors, which will expose their
    state, so we should go out of the gate with the equivalent.  The
    obvious choice is to expose read accessors automatically.  (These
    will not be named getXxx; we are not burning the ill-advised
    Javabean naming conventions into the language, no matter how much
    people think it already is.)  The obvious naming choice for these
    accessors is fieldName().  No provision for write accessors;
    that's bring-your-own.


Method and field named identically is a slight concern. If we gain field references using the same syntax as method references there would probably be no way to refer to such a field. I'm pretty sure this is not worth worrying about though.

I have a story for disambiguating field references...

    Records could be safely made cloneable() with automatic support
    too (like arrays), but not clear if this is worth it (its darn
    useful for arrays, though.)


People just really need to not use arrays anymore, and especially not with records. imho we should have added immutable List and ImmutableIntArray etc. classes a very long time ago. I know we won't now due to our value type aspirations. In the meantime we're in a weird place. Arrays are completely terrible except as micro-optimizations to be used with great care.


OK, but do  you have an opinion on whether records should automatically acquire a clone() implementation?


Reply via email to