<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
</head>
<body text="#000000" bgcolor="#FFFFFF">
<br>
<blockquote type="cite"
cite="mid:CAGKkBkv9k8tpjazREh4ZUbed1RtczwC-rDN_V-bSeY3SFV9wbQ@mail.gmail.com">
<div dir="ltr">
<div class="gmail_extra">
<div class="gmail_quote">
<blockquote class="gmail_quote" style="margin:0 0 0
.8ex;border-left:1px #ccc solid;padding-left:1ex">
<br>
- 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.<br>
</blockquote>
<div><br>
</div>
<div>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.</div>
</div>
</div>
</div>
</blockquote>
<br>
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. <br>
<br>
sealed interface Node;<br>
record ValNode(int value) extends Node;<br>
record VarNode(String name) extends Node;<br>
abstract record BinOpNode(Node left, Node right) extends Node;<br>
record PlusNode(Node left, Node right) extends BinOpNode(left,
right);<br>
record MulNode(Node left, Node right) extends BinOpNode(left,
right);<br>
<br>
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:<br>
<br>
boolean containsVar(Node node, String name) {<br>
return switch (node) {<br>
case VarNode(String s) -> s.equals(name);<br>
case BinOpNode(var left, var right) ->
containsVar(left, name) || containsVar(right, name);<br>
default -> false;<br>
}<br>
}<br>
<br>
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.) <br>
<br>
<blockquote type="cite"
cite="mid:CAGKkBkv9k8tpjazREh4ZUbed1RtczwC-rDN_V-bSeY3SFV9wbQ@mail.gmail.com">
<div dir="ltr">
<div class="gmail_extra">
<div class="gmail_quote"><br>
<div>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).</div>
</div>
</div>
</div>
</blockquote>
<br>
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.) <br>
<br>
<blockquote type="cite"
cite="mid:CAGKkBkv9k8tpjazREh4ZUbed1RtczwC-rDN_V-bSeY3SFV9wbQ@mail.gmail.com">
<div dir="ltr">
<div class="gmail_extra">
<div class="gmail_quote">
<div><br>
</div>
<blockquote class="gmail_quote" style="margin:0 0 0
.8ex;border-left:1px #ccc solid;padding-left:1ex"> -
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.<br>
</blockquote>
<div><br>
</div>
<div>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.</div>
</div>
</div>
</div>
</blockquote>
<br>
I have a story for disambiguating field references...<br>
<br>
<blockquote type="cite"
cite="mid:CAGKkBkv9k8tpjazREh4ZUbed1RtczwC-rDN_V-bSeY3SFV9wbQ@mail.gmail.com">
<div dir="ltr">
<div class="gmail_extra">
<div class="gmail_quote">
<blockquote class="gmail_quote" style="margin:0 0 0
.8ex;border-left:1px #ccc solid;padding-left:1ex">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.)<br>
</blockquote>
<div><br>
</div>
<div>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.</div>
</div>
<br>
</div>
</div>
</blockquote>
<br>
OK, but do you have an opinion on whether records should
automatically acquire a clone() implementation? <br>
<br>
<br>
</body>
</html>