<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
</head>
<body text="#000000" bgcolor="#FFFFFF">
<div class="markdown-here-wrapper" data-md-url="Thunderbird"
style="">
<p style="margin: 0px 0px 1.2em !important;">If we expect values
to “work like an int”, then <code style="font-size: 0.85em; font-family: Consolas, Inconsolata, Courier, monospace;margin: 0px 0.15em; padding: 0px 0.3em; white-space: pre-wrap; border: 1px solid rgb(234, 234, 234); background-color: rgb(248, 248, 248); border-radius: 3px; display: inline;">==</code>
comparisons on value types should work like they do on
primitives:</p>
<pre style="font-size: 0.85em; font-family: Consolas, Inconsolata, Courier, monospace;font-size: 1em; line-height: 1.2em;margin: 1.2em 0px;"><code style="font-size: 0.85em; font-family: Consolas, Inconsolata, Courier, monospace;margin: 0px 0.15em; padding: 0px 0.3em; white-space: pre-wrap; border: 1px solid rgb(234, 234, 234); background-color: rgb(248, 248, 248); border-radius: 3px; display: inline;white-space: pre; overflow: auto; border-radius: 3px; border: 1px solid rgb(204, 204, 204); padding: 0.5em 0.7em; display: block !important;">value class Point { ... }
... client code ...
/* mutable */
Point location;
void setLocation(Point p) {
if (p != location) {
fireExpensivePropertyChangeEvent(location, p);
this.location = p;
}
}
</code></pre>
<p style="margin: 0px 0px 1.2em !important;">Users will reasonably
expect this idiom to work, just as they would for <code style="font-size: 0.85em; font-family: Consolas, Inconsolata, Courier, monospace;margin: 0px 0.15em; padding: 0px 0.3em; white-space: pre-wrap; border: 1px solid rgb(234, 234, 234); background-color: rgb(248, 248, 248); border-radius: 3px; display: inline;">int</code>
properties. </p>
<p style="margin: 0px 0px 1.2em !important;">There have been at
least four suggested treatments of <code style="font-size: 0.85em; font-family: Consolas, Inconsolata, Courier, monospace;margin: 0px 0.15em; padding: 0px 0.3em; white-space: pre-wrap; border: 1px solid rgb(234, 234, 234); background-color: rgb(248, 248, 248); border-radius: 3px; display: inline;">val==</code>:</p>
<ul style="margin: 1.2em 0px;padding-left: 2em;">
<li style="margin: 0.5em 0px;">Illegal; compilation error</li>
<li style="margin: 0.5em 0px;">Always false; user must follow up
with <code style="font-size: 0.85em; font-family: Consolas, Inconsolata, Courier, monospace;margin: 0px 0.15em; padding: 0px 0.3em; white-space: pre-wrap; border: 1px solid rgb(234, 234, 234); background-color: rgb(248, 248, 248); border-radius: 3px; display: inline;">.equals()</code>
test</li>
<li style="margin: 0.5em 0px;">Substitutibility test — are these
the same value</li>
<li style="margin: 0.5em 0px;">Delegate to <code style="font-size: 0.85em; font-family: Consolas, Inconsolata, Courier, monospace;margin: 0px 0.15em; padding: 0px 0.3em; white-space: pre-wrap; border: 1px solid rgb(234, 234, 234); background-color: rgb(248, 248, 248); border-radius: 3px; display: inline;">.equals()</code>
(call this “deep substitutibility”)</li>
</ul>
<p style="margin: 0px 0px 1.2em !important;">I think the first is
unreasonable and should be discarded, based on the above
illustration of failure to “work like an int”; I think the
second is the same. </p>
<p style="margin: 0px 0px 1.2em !important;">We expect generic
code to use the LIFE idiom:</p>
<pre style="font-size: 0.85em; font-family: Consolas, Inconsolata, Courier, monospace;font-size: 1em; line-height: 1.2em;margin: 1.2em 0px;"><code style="font-size: 0.85em; font-family: Consolas, Inconsolata, Courier, monospace;margin: 0px 0.15em; padding: 0px 0.3em; white-space: pre-wrap; border: 1px solid rgb(234, 234, 234); background-color: rgb(248, 248, 248); border-radius: 3px; display: inline;white-space: pre; overflow: auto; border-radius: 3px; border: 1px solid rgb(204, 204, 204); padding: 0.5em 0.7em; display: block !important;">(x == y) || x.equals(y)
</code></pre>
<p style="margin: 0px 0px 1.2em !important;">The LIFE idiom arose
because <code style="font-size: 0.85em; font-family: Consolas, Inconsolata, Courier, monospace;margin: 0px 0.15em; padding: 0px 0.3em; white-space: pre-wrap; border: 1px solid rgb(234, 234, 234); background-color: rgb(248, 248, 248); border-radius: 3px; display: inline;">ref==</code>
is fast, and so we can optimize away the potentially expensive <code style="font-size: 0.85em; font-family: Consolas, Inconsolata, Courier, monospace;margin: 0px 0.15em; padding: 0px 0.3em; white-space: pre-wrap; border: 1px solid rgb(234, 234, 234); background-color: rgb(248, 248, 248); border-radius: 3px; display: inline;">.equals()</code>
call when called with identical objects. But, if the <code style="font-size: 0.85em; font-family: Consolas, Inconsolata, Courier, monospace;margin: 0px 0.15em; padding: 0px 0.3em; white-space: pre-wrap; border: 1px solid rgb(234, 234, 234); background-color: rgb(248, 248, 248); border-radius: 3px; display: inline;">val==</code>
test becomes more expensive, then what started out as an
optimization, might lead to duplication of nontrivial work,
because the <code style="font-size: 0.85em; font-family: Consolas, Inconsolata, Courier, monospace;margin: 0px 0.15em; padding: 0px 0.3em; white-space: pre-wrap; border: 1px solid rgb(234, 234, 234); background-color: rgb(248, 248, 248); border-radius: 3px; display: inline;">.equals()</code>
implementation may well also have an <code style="font-size: 0.85em; font-family: Consolas, Inconsolata, Courier, monospace;margin: 0px 0.15em; padding: 0px 0.3em; white-space: pre-wrap; border: 1px solid rgb(234, 234, 234); background-color: rgb(248, 248, 248); border-radius: 3px; display: inline;">==</code>
test. But, we don’t want to let the optimization tail wag the
dog here. </p>
<p style="margin: 0px 0px 1.2em !important;">Separately, we have
been reluctant to push value substitutibility into <code style="font-size: 0.85em; font-family: Consolas, Inconsolata, Courier, monospace;margin: 0px 0.15em; padding: 0px 0.3em; white-space: pre-wrap; border: 1px solid rgb(234, 234, 234); background-color: rgb(248, 248, 248); border-radius: 3px; display: inline;">acmp</code>,
for fear of perturbing the performance model there. So, let’s
posit a <code style="font-size: 0.85em; font-family: Consolas, Inconsolata, Courier, monospace;margin: 0px 0.15em; padding: 0px 0.3em; white-space: pre-wrap; border: 1px solid rgb(234, 234, 234); background-color: rgb(248, 248, 248); border-radius: 3px; display: inline;">vcmp</code>,
a sibling to <code style="font-size: 0.85em; font-family: Consolas, Inconsolata, Courier, monospace;margin: 0px 0.15em; padding: 0px 0.3em; white-space: pre-wrap; border: 1px solid rgb(234, 234, 234); background-color: rgb(248, 248, 248); border-radius: 3px; display: inline;">{ildf}cmp</code>,
and translate <code style="font-size: 0.85em; font-family: Consolas, Inconsolata, Courier, monospace;margin: 0px 0.15em; padding: 0px 0.3em; white-space: pre-wrap; border: 1px solid rgb(234, 234, 234); background-color: rgb(248, 248, 248); border-radius: 3px; display: inline;">val==</code>
to that, and let <code style="font-size: 0.85em; font-family: Consolas, Inconsolata, Courier, monospace;margin: 0px 0.15em; padding: 0px 0.3em; white-space: pre-wrap; border: 1px solid rgb(234, 234, 234); background-color: rgb(248, 248, 248); border-radius: 3px; display: inline;">acmp</code>
continue to return false when either operand is a value. </p>
<p style="margin: 0px 0px 1.2em !important;">Now, for pure value
code, like the above, we translate <code style="font-size: 0.85em; font-family: Consolas, Inconsolata, Courier, monospace;margin: 0px 0.15em; padding: 0px 0.3em; white-space: pre-wrap; border: 1px solid rgb(234, 234, 234); background-color: rgb(248, 248, 248); border-radius: 3px; display: inline;">val==</code>
to <code style="font-size: 0.85em; font-family: Consolas, Inconsolata, Courier, monospace;margin: 0px 0.15em; padding: 0px 0.3em; white-space: pre-wrap; border: 1px solid rgb(234, 234, 234); background-color: rgb(248, 248, 248); border-radius: 3px; display: inline;">vcmp</code>,
and we work like an int. And for generic code, the LIFE idiom:</p>
<pre style="font-size: 0.85em; font-family: Consolas, Inconsolata, Courier, monospace;font-size: 1em; line-height: 1.2em;margin: 1.2em 0px;"><code style="font-size: 0.85em; font-family: Consolas, Inconsolata, Courier, monospace;margin: 0px 0.15em; padding: 0px 0.3em; white-space: pre-wrap; border: 1px solid rgb(234, 234, 234); background-color: rgb(248, 248, 248); border-radius: 3px; display: inline;white-space: pre; overflow: auto; border-radius: 3px; border: 1px solid rgb(204, 204, 204); padding: 0.5em 0.7em; display: block !important;">x == y || x.equals(y)
</code></pre>
<p style="margin: 0px 0px 1.2em !important;">(when <code style="font-size: 0.85em; font-family: Consolas, Inconsolata, Courier, monospace;margin: 0px 0.15em; padding: 0px 0.3em; white-space: pre-wrap; border: 1px solid rgb(234, 234, 234); background-color: rgb(248, 248, 248); border-radius: 3px; display: inline;">x</code>
and <code style="font-size: 0.85em; font-family: Consolas, Inconsolata, Courier, monospace;margin: 0px 0.15em; padding: 0px 0.3em; white-space: pre-wrap; border: 1px solid rgb(234, 234, 234); background-color: rgb(248, 248, 248); border-radius: 3px; display: inline;">y</code>
are of type <code style="font-size: 0.85em; font-family: Consolas, Inconsolata, Courier, monospace;margin: 0px 0.15em; padding: 0px 0.3em; white-space: pre-wrap; border: 1px solid rgb(234, 234, 234); background-color: rgb(248, 248, 248); border-radius: 3px; display: inline;">T</code>)
translates to an <code style="font-size: 0.85em; font-family: Consolas, Inconsolata, Courier, monospace;margin: 0px 0.15em; padding: 0px 0.3em; white-space: pre-wrap; border: 1px solid rgb(234, 234, 234); background-color: rgb(248, 248, 248); border-radius: 3px; display: inline;">acmp</code>
backed up by an <code style="font-size: 0.85em; font-family: Consolas, Inconsolata, Courier, monospace;margin: 0px 0.15em; padding: 0px 0.3em; white-space: pre-wrap; border: 1px solid rgb(234, 234, 234); background-color: rgb(248, 248, 248); border-radius: 3px; display: inline;">invokevirtual</code>,
and when <code style="font-size: 0.85em; font-family: Consolas, Inconsolata, Courier, monospace;margin: 0px 0.15em; padding: 0px 0.3em; white-space: pre-wrap; border: 1px solid rgb(234, 234, 234); background-color: rgb(248, 248, 248); border-radius: 3px; display: inline;">T</code>
is specialized to a value, the <code style="font-size: 0.85em; font-family: Consolas, Inconsolata, Courier, monospace;margin: 0px 0.15em; padding: 0px 0.3em; white-space: pre-wrap; border: 1px solid rgb(234, 234, 234); background-color: rgb(248, 248, 248); border-radius: 3px; display: inline;">acmp</code>
is fast and always false, and when specialized to a reference,
is fast and computes <code style="font-size: 0.85em; font-family: Consolas, Inconsolata, Courier, monospace;margin: 0px 0.15em; padding: 0px 0.3em; white-space: pre-wrap; border: 1px solid rgb(234, 234, 234); background-color: rgb(248, 248, 248); border-radius: 3px; display: inline;">ref==</code>.
I believe this gives everyone what they want:</p>
<ul style="margin: 1.2em 0px;padding-left: 2em;">
<li style="margin: 0.5em 0px;">value equality is intuitive and
appropriately fast</li>
<li style="margin: 0.5em 0px;">Existing generics continue using
LIFE, and get fast (enough) translation both for reference and
value instantiations</li>
<li style="margin: 0.5em 0px;">Generic code that forgets <code style="font-size: 0.85em; font-family: Consolas, Inconsolata, Courier, monospace;margin: 0px 0.15em; padding: 0px 0.3em; white-space: pre-wrap; border: 1px solid rgb(234, 234, 234); background-color: rgb(248, 248, 248); border-radius: 3px; display: inline;">.equals()</code>
is equally wrong for reference and value instantiations</li>
<li style="margin: 0.5em 0px;">Generic code that goes straight
to <code style="font-size: 0.85em; font-family: Consolas, Inconsolata, Courier, monospace;margin: 0px 0.15em; padding: 0px 0.3em; white-space: pre-wrap; border: 1px solid rgb(234, 234, 234); background-color: rgb(248, 248, 248); border-radius: 3px; display: inline;">.equals()</code>
works correctly for reference and value instantiation</li>
</ul>
<div
title="MDH:PHR0PklmIHdlIGV4cGVjdCB2YWx1ZXMgdG8gIndvcmsgbGlrZSBhbiBpbnQiLCB0aGVuIGA9PWAg
Y29tcGFyaXNvbnMgb24gdmFsdWUgdHlwZXMgc2hvdWxkIHdvcmsgbGlrZSB0aGV5IGRvIG9uIHBy
aW1pdGl2ZXM6PGJyPjxicj4mbmJzcDsmbmJzcDsmbmJzcDsgdmFsdWUgY2xhc3MgUG9pbnQgeyAu
Li4gfTxicj48YnI+Jm5ic3A7Jm5ic3A7Jm5ic3A7IC4uLiBjbGllbnQgY29kZSAuLi48YnI+PGJy
PiZuYnNwOyZuYnNwOyZuYnNwOyAvKiBtdXRhYmxlICovPGJyPiZuYnNwOyZuYnNwOyZuYnNwOyBQ
b2ludCBsb2NhdGlvbjs8YnI+PGJyPiZuYnNwOyZuYnNwOyZuYnNwOyB2b2lkIHNldExvY2F0aW9u
KFBvaW50IHApIHs8YnI+Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7
IGlmIChwICE9IGxvY2F0aW9uKSB7PGJyPiZuYnNwOyZuYnNwOyZuYnNwOyZuYnNwOyZuYnNwOyZu
YnNwOyZuYnNwOyZuYnNwOyZuYnNwOyZuYnNwOyZuYnNwOyBmaXJlRXhwZW5zaXZlUHJvcGVydHlD
aGFuZ2VFdmVudChsb2NhdGlvbiwgcCk7PGJyPiZuYnNwOyZuYnNwOyZuYnNwOyZuYnNwOyZuYnNw
OyZuYnNwOyZuYnNwOyZuYnNwOyZuYnNwOyZuYnNwOyZuYnNwOyB0aGlzLmxvY2F0aW9uID0gcDs8
YnI+Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7Jm5ic3A7IH08YnI+Jm5ic3A7
Jm5ic3A7Jm5ic3A7IH08YnI+PGJyPlVzZXJzIHdpbGwgcmVhc29uYWJseSBleHBlY3QgdGhpcyBp
ZGlvbSB0byB3b3JrLCBqdXN0IGFzIHRoZXkgd291bGQgZm9yIGBpbnRgIHByb3BlcnRpZXMuJm5i
c3A7IDxicj48YnI+VGhlcmUgaGF2ZSBiZWVuIGF0IGxlYXN0IGZvdXIgc3VnZ2VzdGVkIHRyZWF0
bWVudHMgb2YgYHZhbD09YDo8YnI+PGJyPiZuYnNwOy0gSWxsZWdhbDsgY29tcGlsYXRpb24gZXJy
b3I8YnI+Jm5ic3A7LSBBbHdheXMgZmFsc2U7IHVzZXIgbXVzdCBmb2xsb3cgdXAgd2l0aCBgLmVx
dWFscygpYCB0ZXN0PGJyPiZuYnNwOy0gU3Vic3RpdHV0aWJpbGl0eSB0ZXN0IC0tIGFyZSB0aGVz
ZSB0aGUgc2FtZSB2YWx1ZTxicj4mbmJzcDstIERlbGVnYXRlIHRvIGAuZXF1YWxzKClgIChjYWxs
IHRoaXMgImRlZXAgc3Vic3RpdHV0aWJpbGl0eSIpPGJyPjxicj5JIHRoaW5rIHRoZSBmaXJzdCBp
cyB1bnJlYXNvbmFibGUgYW5kIHNob3VsZCBiZSBkaXNjYXJkZWQsIGJhc2VkIG9uIHRoZSBhYm92
ZSBpbGx1c3RyYXRpb24gb2YgZmFpbHVyZSB0byAid29yayBsaWtlIGFuIGludCI7IEkgdGhpbmsg
dGhlIHNlY29uZCBpcyB0aGUgc2FtZS4mbmJzcDsgPGJyPjxicj5XZSBleHBlY3QgZ2VuZXJpYyBj
b2RlIHRvIHVzZSB0aGUgTElGRSBpZGlvbTo8YnI+PGJyPiZuYnNwOyZuYnNwOyZuYnNwOyAoeCA9
PSB5KSB8fCB4LmVxdWFscyh5KTxicj48YnI+VGhlIExJRkUgaWRpb20gYXJvc2UgYmVjYXVzZSBg
cmVmPT1gIGlzIGZhc3QsIGFuZCBzbyB3ZSBjYW4gb3B0aW1pemUgYXdheSB0aGUgcG90ZW50aWFs
bHkgZXhwZW5zaXZlIGAuZXF1YWxzKClgIGNhbGwgd2hlbiBjYWxsZWQgd2l0aCBpZGVudGljYWwg
b2JqZWN0cy4mbmJzcDsgQnV0LCBpZiB0aGUgYHZhbD09YCB0ZXN0IGJlY29tZXMgbW9yZSBleHBl
bnNpdmUsIHRoZW4gd2hhdCBzdGFydGVkIG91dCBhcyBhbiBvcHRpbWl6YXRpb24sIG1pZ2h0IGxl
YWQgdG8gZHVwbGljYXRpb24gb2Ygbm9udHJpdmlhbCB3b3JrLCBiZWNhdXNlIHRoZSBgLmVxdWFs
cygpYCBpbXBsZW1lbnRhdGlvbiBtYXkgd2VsbCBhbHNvIGhhdmUgYW4gYD09YCB0ZXN0LiZuYnNw
OyBCdXQsIHdlIGRvbid0IHdhbnQgdG8gbGV0IHRoZSBvcHRpbWl6YXRpb24gdGFpbCB3YWcgdGhl
IGRvZyBoZXJlLiZuYnNwOyA8YnI+PGJyPlNlcGFyYXRlbHksIHdlIGhhdmUgYmVlbiByZWx1Y3Rh
bnQgdG8gcHVzaCB2YWx1ZSBzdWJzdGl0dXRpYmlsaXR5IGludG8gYGFjbXBgLCBmb3IgZmVhciBv
ZiBwZXJ0dXJiaW5nIHRoZSBwZXJmb3JtYW5jZSBtb2RlbCB0aGVyZS4mbmJzcDsgU28sIGxldCdz
IHBvc2l0IGEgYHZjbXBgLCBhIHNpYmxpbmcgdG8gYHtpbGRmfWNtcGAsIGFuZCB0cmFuc2xhdGUg
YHZhbD09YCB0byB0aGF0LCBhbmQgbGV0IGBhY21wYCBjb250aW51ZSB0byByZXR1cm4gZmFsc2Ug
d2hlbiBlaXRoZXIgb3BlcmFuZCBpcyBhIHZhbHVlLiZuYnNwOyA8YnI+PGJyPk5vdywgZm9yIHB1
cmUgdmFsdWUgY29kZSwgbGlrZSB0aGUgYWJvdmUsIHdlIHRyYW5zbGF0ZSBgdmFsPT1gIHRvIGB2
Y21wYCwgYW5kIHdlIHdvcmsgbGlrZSBhbiBpbnQuJm5ic3A7IEFuZCBmb3IgZ2VuZXJpYyBjb2Rl
LCB0aGUgTElGRSBpZGlvbTo8YnI+PGJyPiZuYnNwOyZuYnNwOyZuYnNwOyB4ID09IHkgfHwgeC5l
cXVhbHMoeSk8YnI+PGJyPih3aGVuIGB4YCBhbmQgYHlgIGFyZSBvZiB0eXBlIGBUYCkgdHJhbnNs
YXRlcyB0byBhbiBgYWNtcGAgYmFja2VkIHVwIGJ5IGFuIGBpbnZva2V2aXJ0dWFsYCwgYW5kIHdo
ZW4gYFRgIGlzIHNwZWNpYWxpemVkIHRvIGEgdmFsdWUsIHRoZSBgYWNtcGAgaXMgZmFzdCBhbmQg
YWx3YXlzIGZhbHNlLCBhbmQgd2hlbiBzcGVjaWFsaXplZCB0byBhIHJlZmVyZW5jZSwgaXMgZmFz
dCBhbmQgY29tcHV0ZXMgYHJlZj09YC4mbmJzcDsgSSBiZWxpZXZlIHRoaXMgZ2l2ZXMgZXZlcnlv
bmUgd2hhdCB0aGV5IHdhbnQ6PGJyPjxicj4mbmJzcDstIHZhbHVlIGVxdWFsaXR5IGlzIGludHVp
dGl2ZSBhbmQgYXBwcm9wcmlhdGVseSBmYXN0PGJyPiZuYnNwOy0gRXhpc3RpbmcgZ2VuZXJpY3Mg
Y29udGludWUgdXNpbmcgTElGRSwgYW5kIGdldCBmYXN0IChlbm91Z2gpIHRyYW5zbGF0aW9uIGJv
dGggZm9yIHJlZmVyZW5jZSBhbmQgdmFsdWUgaW5zdGFudGlhdGlvbnM8YnI+Jm5ic3A7LSBHZW5l
cmljIGNvZGUgdGhhdCBmb3JnZXRzIGAuZXF1YWxzKClgIGlzIGVxdWFsbHkgd3JvbmcgZm9yIHJl
ZmVyZW5jZSBhbmQgdmFsdWUgaW5zdGFudGlhdGlvbnM8YnI+Jm5ic3A7LSBHZW5lcmljIGNvZGUg
dGhhdCBnb2VzIHN0cmFpZ2h0IHRvIGAuZXF1YWxzKClgIHdvcmtzIGNvcnJlY3RseSBmb3IgcmVm
ZXJlbmNlIGFuZCB2YWx1ZSBpbnN0YW50aWF0aW9uPGJyPjxicj48YnI+PGJyPjwvdHQ+"
style="height:0;width:0;max-height:0;max-width:0;overflow:hidden;font-size:0em;padding:0;margin:0;"></div>
</div>
</body>
</html>