<!DOCTYPE html><html><head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
</head>
<body>
<blockquote type="cite" cite="mid:CANSoFxtysPkbbaetD0M5GStp_wdWFVhUPc0ig_CKCbS556dKJA@mail.gmail.com">
<div dir="ltr">
<div class="gmail_quote gmail_quote_container">
<div>That's a good requirement, and I agree that identity
equality is wrong for records and carriers, but there was
another way we could have achieved this requirement, i.e, by
using value equality (i.e., using == on each component)
instead of recursive equality (using equals() on each
component) or identity equality (using == on this &
that).</div>
<div><br>
</div>
<div>Asking in another way, how would you describe the
conceptual distinction between a record and a value class?</div>
</div>
</div>
</blockquote>
<br>
There is a lot of overlap; I would expect that many records/carriers
can be value records/carriers, and many value classes can be
carriers/records -- but neither subsumes the other. <br>
<br>
The essence of value-ness is the lack of identity (and all that
implies -- no mutability, no layout polymorphism, no monitor, no
self-recursion, etc.) The main semantic implication is that this
changes the meaning of `==` (and hence the default Object::equals)
to be state-based. But this is not as broadly useful as it sounds;
once you get away from the things that are truly "value all the way
down" (numbers, dates, etc) and start to talk about value classes
whose fields are identity objects (including, sadly, strings), then
`==` reasserts its limitations. This is imperfect but it is the
least imperfect thing we can do given the historical meaning of `==`
and the gazillions of lines of code that have been written around
that meaning. So while values get a "better" `==` out of the box,
`==` remains a low-level mechanism best left to low-level code. <br>
<br>
The essence of record-ness is alignment of external and internal
representations. (This assumes a record _has_ an external
representation, the semantics of which are being subsumed by
carriers.) For types that "just" represent possibly-constrained
products, records are an ideal choice. <br>
<br>
(To complete the story, the essence of carrier-ness is that there is
a state description, which describes the "external representation",
and that external representation is complete, canonical, and
nominal. This puts construction, deconstruction, and reconstruction
on solid ground.)<br>
<br>
Each of value-ness / record-ness means giving something up and
getting something in return. If you are willing to give up both set
of things, you get both sets of benefits. Many classes will fit
into that story, such as <br>
<br>
value record Rational(int num, int denom) { ... }<br>
value record DateTime(Date date, Time time) { ... } // where
Date and Time are values<br>
value record Complex(double real, double imag) { ... }<br>
<br>
(Whether or not Rational overrides equals() depends on whether the
constructor normalizes to lowest terms; if the constructor reduces
preemptively, then `==` is all that is needed and we can inherit
Object::equals, but either way we would expect `new Rational(2,4)`
and `new Rational(3,6)` to be equals.) <br>
<br>
The introduction of carriers means many of the properties that used
to be properties of records are now properties of carriers
(deconstruction patterns, the take-it-apart-and-put-it-together
guarantee, etc); the difference between records and carriers (as
proposed) is that records are a _particular example_ of carriers,
but all the semantic guarantees come from carrier-ness. Which makes
your question: what is the difference between values and carriers?<br>
<br>
The difference is:<br>
- Carriers are tightly constrained to a specific relationship
between their put-it-together behaviors (constructors) and their
take-it-apart behaviors (accessors, deconstruction), that is
consistent with equality, but they are allowed to use identity and
all the things it implies. Carriers get semantic benefits (e.g.
reconstruction) in exchange for this deal.<br>
- Values can be cagier about their implementation (they can be
complete black boxes), but are constrained to not use identity and
all the things it implies. Values get runtime benefits (e.g.,
flattening) in exchange for this deal.<br>
<br>
The deals are not mutually exclusive.<br>
<br>
<br>
</body>
</html>