<html><head><meta http-equiv="Content-Type" content="text/html; charset=utf-8"></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; line-break: after-white-space;" class=""><div class=""><br class=""></div><div class="">This matches with my first-read gut-interpretation as well. Even though this might be technically an accurate use of the word, when I read “lexicographically” that implies to me a “natural ordering of the elements", not whatever the ordering happens to be on the collection at that time, so that I would expect:</div><div class=""><br class=""></div><div class="">[“A”, “B”, “C”].lexographicallyEquals([“B”, “A”, “C”]) // true</div><div class=""><br class=""></div><div class="">Especially since the additional qualification over “equals” serves to emphasize the “lexographically” in reading the API (ie: not just “equals” but “lexographically equals”). Sure, maybe that’s a mis-reading of “lexicographically”, but it’s a pretty natural one, and a quick non-scientific poll of a few developers I work with had either a similar reading, or didn’t know what the function might mean. In either case, this naming seems contrary to the Swift API goal of “Clarity at the call site”.</div><div class=""><br class=""></div><div class="">So -1 from me for this name.</div><div class=""><br class=""></div><div class="">If we really want to rename this, what about something like:</div><div class=""><br class=""></div><div class=""><div class="">[“A”, “B”, “C”].isOrderedEqual(to: [“B”, “A”, “C”]) // false</div></div><div class=""><div class="">[“A”, “B”, “C”].isOrderedEqual(to:&nbsp;[“A”, “B”, “C”]) // true</div></div><div class=""><div class="">[“A”, “B”, “C”].isOrderedEqual(to:&nbsp;[“A”, “B”, “D”]) // false</div></div><div class=""><br class=""></div><div class="">---</div><div class=""><br class=""></div>On the other hand, I’m also very much +1 for “Split&nbsp;Iterable out of Sequence” as soon as possible (even 4.x if possible)<div class=""><br class=""></div><div class="">Yes, this will be a breaking change. But the longer we let this obviously wrong modeling of Dictionary &amp; Set linger, 1) the bigger a breaking change it will be, and 2) the more fundamentally unsafe code and undefined behavior will be written in Swift, directly undermining the language’s claims to safety by design.&nbsp;</div><div class=""><br class=""></div><div class="">Perhaps we could mitigate some of the breakage by retaining the “broken” interfaces on Iterable with deprecation notices, but I haven’t through that through very much.</div><div class=""><br class=""></div><div class="">—Karim</div><div class=""><br class=""></div><div class=""><div class=""><div><blockquote type="cite" class=""><div class="">On Oct 13, 2017, at 5:52 PM, <a href="mailto:swift-evolution-request@swift.org" class="">swift-evolution-request@swift.org</a> wrote:</div><br class="Apple-interchange-newline"><div class=""><span style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; float: none; display: inline !important;" class="">From: Christopher Whidden &lt;</span><a href="mailto:christopher.whidden@gmail.com" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px;" class="">christopher.whidden@gmail.com</a><span style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; float: none; display: inline !important;" class="">&gt;</span><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><span style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; float: none; display: inline !important;" class="">To: Xiaodi Wu &lt;</span><a href="mailto:xiaodi.wu@gmail.com" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px;" class="">xiaodi.wu@gmail.com</a><span style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; float: none; display: inline !important;" class="">&gt;</span><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><span style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; float: none; display: inline !important;" class="">Cc: swift-evolution &lt;</span><a href="mailto:swift-evolution@swift.org" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px;" class="">swift-evolution@swift.org</a><span style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; float: none; display: inline !important;" class="">&gt;</span><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><span style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; float: none; display: inline !important;" class="">Subject: Re: [swift-evolution] [Draft] Rename Sequence.elementsEqual</span><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><span style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; float: none; display: inline !important;" class="">Message-ID: &lt;</span><a href="mailto:DEA22A3B-741E-4AA9-B922-7C123032B160@gmail.com" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px;" class="">DEA22A3B-741E-4AA9-B922-7C123032B160@gmail.com</a><span style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; float: none; display: inline !important;" class="">&gt;</span><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><span style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; float: none; display: inline !important;" class="">Content-Type: text/plain; charset="utf-8"</span><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><span style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; float: none; display: inline !important;" class="">Using the term “lexicographically” implies to me that the Element type must conform to Comparable, as would be required for a total order. &nbsp;The Sequence method you mention, lexicographicallyPrecedes(_:), does have this constraint, whereas the method in question for elementsEqual(_:) / lexicographicallyEquals(_:) only has the constraint that the Element is Equatable. &nbsp;As an example, an array of simple enums has no default lexicographical ordering but is still able to use this method because enums (without associated values) are Equatable by default:</span><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><span style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; float: none; display: inline !important;" class="">enum Foo {</span><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><span style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; float: none; display: inline !important;" class="">&nbsp;&nbsp;&nbsp;case bar</span><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><span style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; float: none; display: inline !important;" class="">&nbsp;&nbsp;&nbsp;case baz</span><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><span style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; float: none; display: inline !important;" class="">}</span><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><span style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; float: none; display: inline !important;" class="">let f1 = [Foo.bar, Foo.baz]</span><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><span style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; float: none; display: inline !important;" class="">let f2 = [Foo.baz, Foo.bar]</span><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><span style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; float: none; display: inline !important;" class="">f1.elementsEqual(f2) //false</span><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><span style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; float: none; display: inline !important;" class="">f1.elementsEqual(f2.reversed()) //true</span><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><span style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; float: none; display: inline !important;" class="">I also share Jonathan’s concerns that some programmers may misinterpret [lexicographically][Equals] to mean [sorted in lexicographical order][compare sequence equality], which is not what the method in question does.</span><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><span style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; float: none; display: inline !important;" class="">Xiaodi, I think you are right that Sequence.sequentiallyEquals is to close to "==" to use, but I think we have to find something better here.</span><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><span style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; float: none; display: inline !important;" class="">I’ll recommend that we use the name Sequence.iterativelyEquals(_:) since this describes the body of the method concisely. &nbsp;A rough abbreviation of this algorithm is:</span><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><span style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; float: none; display: inline !important;" class="">1. Iterate over elements in two sequences</span><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><span class="Apple-tab-span" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: pre; word-spacing: 0px; -webkit-text-stroke-width: 0px;">        </span><span style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; float: none; display: inline !important;" class="">a. Compare elements for equality</span><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><span style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; float: none; display: inline !important;" class="">“iterativelyEquals" concisely describes this.</span><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><blockquote type="cite" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px;" class="">On Oct 12, 2017, at 6:24 PM, Xiaodi Wu via swift-evolution &lt;<a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a>&gt; wrote:<br class=""><br class="">Rename Sequence.elementsEqual<br class=""><br class="">Proposal: SE-NNNN &lt;<a href="https://gist.github.com/xwu/NNNN-rename-elements-equal.md" class="">https://gist.github.com/xwu/NNNN-rename-elements-equal.md</a>&gt;<br class="">Authors: Xiaodi Wu &lt;<a href="https://github.com/xwu" class="">https://github.com/xwu</a>&gt;<br class="">Review Manager: TBD<br class="">Status: Awaiting review<br class="">&lt;<a href="https://gist.github.com/xwu/1f0ef4e18a7f321f22ca65a2f56772f6#introduction" class="">https://gist.github.com/xwu/1f0ef4e18a7f321f22ca65a2f56772f6#introduction</a>&gt;Introduction<br class=""><br class="">The current behavior of Sequence.elementsEqual is potentially confusing to users given its name. Having surveyed the alternative solutions to this problem, it is proposed that the method be renamed to Sequence.lexicographicallyEquals.<br class=""><br class="">&lt;<a href="https://gist.github.com/xwu/1f0ef4e18a7f321f22ca65a2f56772f6#motivation" class="">https://gist.github.com/xwu/1f0ef4e18a7f321f22ca65a2f56772f6#motivation</a>&gt;Motivation<br class=""><br class="">As outlined by Ole Begemann &lt;<a href="https://twitter.com/olebegemann/status/916291785185529857" class="">https://twitter.com/olebegemann/status/916291785185529857</a>&gt;, use of Sequence.elementsEqual(_:) can lead to surprising results if the sequences compared are unordered:<br class=""><br class="">var set1: Set&lt;Int&gt; = Set(1...5)<br class="">var set2: Set&lt;Int&gt; = Set((1...5).reversed())<br class=""><br class="">set1 == set2 // true<br class="">set1.elementsEqual(set2) // false<br class="">This result does reflect the intended and documented behavior of the elementsEqual(_:) method, which performs a lexicographical elementwise comparison. That is, the method first compares set1.first to set2.first, then (if the two elements compare equal) compares the next element stored internally in set1 to the next element stored internally in set2, and so on.<br class=""><br class="">In almost all circumstances where a set is compared to another set, or a dictionary is compared to another dictionary, users should use == instead of elementsEqual(_:).<br class=""><br class="">&lt;<a href="https://gist.github.com/xwu/1f0ef4e18a7f321f22ca65a2f56772f6#proposed-solution" class="">https://gist.github.com/xwu/1f0ef4e18a7f321f22ca65a2f56772f6#proposed-solution</a>&gt;Proposed solution<br class=""><br class="">The proposed solution is the result of an iterative process of reasoning, presented here:<br class=""><br class="">The first and most obvious solution is to remove the elementsEqual(_:) method altogether in favor of ==. This prevents its misuse. However, because elementsEqual(_:) is a generic method on Sequence, we can use it to compare an instance of UnsafeBufferPointer&lt;Int&gt; to an instance of [Int]. This is a useful and non-redundant feature which would be eliminated if the method is removed altogether.<br class=""><br class="">A second solution &lt;<a href="https://github.com/apple/swift/pull/12318" class="">https://github.com/apple/swift/pull/12318</a>&gt; is to create overloads that forbid the use of the elementsEqual(_:) method specifically in non-generic code. This would prevent misuse in non-generic code; however, it would also forbid legitimate mixed-type comparisons in non-generic code while failing to prevent misuse in generic code. The solution also creates a difference in the behavior of generic and non-generic code calling the same method, which is potentially confusing, without solving the problem completely.<br class=""><br class="">A third solution is to dramatically overhaul the protocol hierarchy for Swift sequences and collections so that unordered collections no longer have members such as first and elementsEqual(_:). However, this would be a colossal and source-breaking undertaking, and it is unlikely to be satisfactory in addressing all the axes of differences among sequence and collection types:<br class=""><br class="">Finite versus infinite<br class="">Single-pass versus multi-pass<br class="">Ordered versus unordered<br class="">Lazy versus eager<br class="">Forward/bidirectional/random-access<br class="">A fourth solution is proposed here. It is predicated on the following observation:<br class=""><br class="">Another method similar to elementsEqual(_:) already exists on Sequence named lexicographicallyPrecedes(_:). Like first, elementsEqual(_:), drop(while:), and others, it relies on the internal order of elements in a manner that is not completely suitable for an unordered collection. However, like first and unlike elementsEqual(_:), this fact is called out in the name of the method; unsurprisingly, like first and unlike elementsEqual(_:), there is no evidence that lexicographicallyPrecedes(_:) has been a pitfall for users.<br class=""><br class="">This observation suggests that a major reason for confusion over elementsEqual(_:) stems from its name. So, it is proposed that elementsEqual(_:) should be renamed to lexicographicallyEquals(_:). The function will remain somewhat of a poor fit for unordered collections, but no more so than many other methods that cannot trivially be removed from the API of unordered collections (as discussed above). The key is that, with such a renaming, the behavior of this method will no longer be confusing.<br class=""><br class="">&lt;<a href="https://gist.github.com/xwu/1f0ef4e18a7f321f22ca65a2f56772f6#detailed-design" class="">https://gist.github.com/xwu/1f0ef4e18a7f321f22ca65a2f56772f6#detailed-design</a>&gt;Detailed design<br class=""><br class="">extension Sequence where Element : Equatable {<br class="">&nbsp;@available(*, deprecated, message: "Use '==' if possible to compare two sequences of the same type, or use 'lexicographicallyEquals' to compare two ordered sequences.")<br class="">&nbsp;public func elementsEqual&lt;Other : Sequence&gt;(<br class="">&nbsp;&nbsp;&nbsp;_ other: Other<br class="">&nbsp;) -&gt; Bool where Other.Element == Element {<br class="">&nbsp;&nbsp;&nbsp;return lexicographicallyEquals(other)<br class="">&nbsp;}<br class=""><br class="">&nbsp;public func lexicographicallyEquals&lt;Other : Sequence&gt;(<br class="">&nbsp;&nbsp;&nbsp;_ other: Other<br class="">&nbsp;) -&gt; Bool where Other.Element == Element {<br class="">&nbsp;&nbsp;&nbsp;// The body of this method is unchanged.<br class="">&nbsp;&nbsp;&nbsp;var iter1 = self.makeIterator()<br class="">&nbsp;&nbsp;&nbsp;var iter2 = other.makeIterator()<br class="">&nbsp;&nbsp;&nbsp;while true {<br class="">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;switch (iter1.next(), iter2.next()) {<br class="">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;case let (e1?, e2?):<br class="">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if e1 != e2 { return false }<br class="">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;case (_?, nil), (nil, _?):<br class="">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return false<br class="">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;case (nil, nil):<br class="">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return true<br class="">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br class="">&nbsp;&nbsp;&nbsp;}<br class="">&nbsp;}<br class="">}<br class="">A parallel change will be made with respect to elementsEqual(_:by:); that is, it will be deprecated in favor of lexicographicallyEquals(_:by:).<br class=""><br class="">&lt;<a href="https://gist.github.com/xwu/1f0ef4e18a7f321f22ca65a2f56772f6#source-compatibility" class="">https://gist.github.com/xwu/1f0ef4e18a7f321f22ca65a2f56772f6#source-compatibility</a>&gt;Source compatibility<br class=""><br class="">Existing code that uses elementsEqual will gain a deprecation warning.<br class=""><br class="">&lt;<a href="https://gist.github.com/xwu/1f0ef4e18a7f321f22ca65a2f56772f6#effect-on-abi-stability" class="">https://gist.github.com/xwu/1f0ef4e18a7f321f22ca65a2f56772f6#effect-on-abi-stability</a>&gt;Effect on ABI stability<br class=""><br class="">None.<br class=""><br class="">&lt;<a href="https://gist.github.com/xwu/1f0ef4e18a7f321f22ca65a2f56772f6#effect-on-api-resilience" class="">https://gist.github.com/xwu/1f0ef4e18a7f321f22ca65a2f56772f6#effect-on-api-resilience</a>&gt;Effect on API resilience<br class=""><br class="">This proposal adds new methods to the public API of Sequence and conforming types.<br class=""><br class="">&lt;<a href="https://gist.github.com/xwu/1f0ef4e18a7f321f22ca65a2f56772f6#alternatives-considered" class="">https://gist.github.com/xwu/1f0ef4e18a7f321f22ca65a2f56772f6#alternatives-considered</a>&gt;Alternatives considered<br class=""><br class="">It is to be noted that lexicographicallyPrecedes(_:by:) and elementsEqual(_:by:) are essentially the same method, since both perform a lexicographical comparison using a custom predicate. However, there is not a good unifying name. (lexicographicallyCompares(to:by:) reads poorly.) Moreover, the predicate supplied is intended to have very different semantics, and maintaining two distinct methods may be a superior fit with the typical user's mental model of the intended behavior and may also be clearer to readers of the code. Therefore, this proposal does not seek to unify the two methods; instead, elementsEqual(_:by:) will be renamed lexicographicallyEquals(_:by:) as detailed above.<br class=""><br class="">_______________________________________________<br class="">swift-evolution mailing list<br class=""><a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a><br class=""><a href="https://lists.swift.org/mailman/listinfo/swift-evolution" class="">https://lists.swift.org/mailman/listinfo/swift-evolution</a><br class=""></blockquote><br class="Apple-interchange-newline"></div></blockquote></div><br class=""></div></div></body></html>