<!DOCTYPE html>
<html>
<head>
<title></title>
</head>
<body><div>On Tue, Oct 17, 2017, at 20:46, Xiaodi Wu via swift-evolution wrote:<br></div>
<blockquote type="cite"><div><div defang_data-gmailquote="yes"><div>On Tue, Oct 17, 2017 at 12:54 Jonathan Hull <<a href="mailto:jhull@gbis.com">jhull@gbis.com</a>> wrote:<br></div>
<div><br></div>
<blockquote defang_data-gmailquote="yes" style="margin-top:0px;margin-right:0px;margin-bottom:0px;margin-left:0.8ex;border-left-width:1px;border-left-style:solid;border-left-color:rgb(204, 204, 204);padding-left:1ex;"><div style="word-wrap:break-word;"><div><div>Why was elementsEqual created? Isn’t it meant to check equality of two sequences in a generic context where == isn’t available?<br></div>
</div>
</div>
</blockquote><div><br></div>
<div>No no no no no no no no. That’s precisely why the name is misleading. elementsEqual is *not* simply a mixed-type version of ==. Remember that == as implemented on a concrete sequence type *has no obligation* to use elementwise comparison using the element’s implementation of ==. This is not merely theoretical: [Float].== does *not* do an elementwise comparison using Float.==. By contrast, you are guaranteed a true elementwise comparison with elementsEqual regardless of how equivalence is defined for the sequence.<br></div>
</div>
</div>
</blockquote><div><br></div>
<div>Really? I would have thought an elementwise comparison is exactly what [Float].== would do.<br></div>
<div><br></div>
<div>I tested this and these are the (very surprising, at least to me) results:<br></div>
<div><br></div>
<div><span class="highlight" style="background-color:rgb(255, 255, 255)"><span class="colour" style="color:rgb(0, 0, 0)"><span class="font" style="font-family:Menlo"><span class="colour" style="color:rgb(186, 45, 162)">let</span> numbers: [<span class="colour" style="color:rgb(112, 61, 170)">Float</span>] = [<span class="colour" style="color:rgb(39, 42, 216)">1</span>, .<span class="colour" style="color:rgb(112, 61, 170)">nan</span>]</span></span></span><br></div>
<div><span class="highlight" style="background-color:rgb(255, 255, 255)"><span class="colour" style="color:rgb(0, 0, 0)"><span class="font" style="font-family:Menlo"><span class="colour" style="color:rgb(186, 45, 162)">let</span> copy = <span class="colour" style="color:rgb(79, 129, 135)">numbers</span></span></span></span><br></div>
<div><span class="highlight" style="background-color:rgb(255, 255, 255)"><span class="colour" style="color:rgb(0, 0, 0)"><span class="font" style="font-family:Menlo"><span class="colour" style="color:rgb(186, 45, 162)">let</span> sameNumbers: [<span class="colour" style="color:rgb(112, 61, 170)">Float</span>] = [<span class="colour" style="color:rgb(39, 42, 216)">1</span>, .<span class="colour" style="color:rgb(112, 61, 170)">nan</span>]</span></span></span><br></div>
<div><br></div>
<div><span class="highlight" style="background-color:rgb(255, 255, 255)"><span class="colour" style="color:rgb(0, 0, 0)"><span class="font" style="font-family:Menlo"><span class="colour" style="color:rgb(79, 129, 135)">numbers</span> == <span class="colour" style="color:rgb(79, 129, 135)">copy</span> <span class="colour" style="color:rgb(0, 132, 0)">// (1) true (!)</span></span></span></span><br></div>
<div><span class="highlight" style="background-color:rgb(255, 255, 255)"><span class="colour" style="color:rgb(79, 129, 135)"><span class="font" style="font-family:Menlo">numbers<span class="colour" style="color:rgb(0, 0, 0)"> == </span>sameNumbers<span class="colour" style="color:rgb(0, 0, 0)"> </span><span class="colour" style="color:rgb(0, 132, 0)">// (2) false (!)</span></span></span></span><br></div>
<div><span class="highlight" style="background-color:rgb(255, 255, 255)"><span class="colour" style="color:rgb(62, 30, 129)"><span class="font" style="font-family:Menlo"><span class="colour" style="color:rgb(79, 129, 135)">numbers</span><span class="colour" style="color:rgb(0, 0, 0)">.</span>elementsEqual<span class="colour" style="color:rgb(0, 0, 0)">(</span><span class="colour" style="color:rgb(79, 129, 135)">copy</span><span class="colour" style="color:rgb(0, 0, 0)">) </span><span class="colour" style="color:rgb(0, 132, 0)">// (3) false (ok)</span></span></span></span><br></div>
<div><span class="highlight" style="background-color:rgb(255, 255, 255)"><span class="colour" style="color:rgb(79, 129, 135)"><span class="font" style="font-family:Menlo">numbers<span class="colour" style="color:rgb(0, 0, 0)">.</span><span class="colour" style="color:rgb(62, 30, 129)">elementsEqual</span><span class="colour" style="color:rgb(0, 0, 0)">(</span>sameNumbers<span class="colour" style="color:rgb(0, 0, 0)">) </span><span class="colour" style="color:rgb(0, 132, 0)">// (4) false (ok)</span></span></span></span><br></div>
<div><br></div>
<div>So [Float].== returns a different result depending on whether you compare two arrays that share the same buffer (1) or two arrays with the same contents (2) when the array contains NaN. The reason is that Array.== immediately returns true <a href="https://github.com/apple/swift/blob/master/stdlib/public/core/Arrays.swift.gyb#L2194-L2197">if two arrays share the same buffer</a>.<br></div>
<div><br></div>
<div>Even knowing that comparing floats is problematic in the context of NaN (and in general), I find this very surprising. It also seems to clash with <a href="https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20171016/040544.html">Michael's idea</a> that two substitutable sequences should return true for ==.<br></div>
<div><br></div>
</body>
</html>