<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="">I think that “match” is a word to avoid for this, as this doesn’t have anything to do with pattern matching, fuzzy matching, etc., while “equals” is precisely the concept we’re using.</div><div class=""><br class=""></div><div class="">What about the name “sequentiallyEquals”? Highlight the fact that we’re talking about sequential ordering, i.e. whatever order the sequence provides, as opposed to first doing some lexicographical ordering of elements themselves.</div><div class=""><br class=""></div><div class="">var a: Set<Int> = [3, 1, 2]</div><div class="">a.sequentiallyEquals([1,2,3]) // result depends on application of equality in a (potentially-arbitrary) sequential ordering</div><div class=""><br class=""></div><div class="">Whereas I could see the following being more confusing:</div><div class=""><br class=""></div><div class=""><div class="">var a: Set<Int> = [3, 1, 2]</div><div class="">a.lexicographicallyEquals([1,2,3]) // result depends on application of equality, but what meaning does “lexicographically” convey?</div></div><div class=""><br class=""></div><div class="">It’s not immediately clear to someone new to the API that “lexicographically” speaks to the nature of the sequence’s (potentially-arbitrary) order, irrespective of element. It could give the false impression that it speaks to some nature of the elements themselves, in this case Ints, which have an obvious lexicographical ordering. I don’t know how frequent that misconception would be in practice, but it does cause me to do a double-take in this contrived example.</div><div class=""><br class=""></div><div class=""><br class=""></div><div><blockquote type="cite" class=""><div class="">On Oct 14, 2017, at 1:04 PM, Benjamin G via swift-evolution <<a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a>> wrote:</div><br class="Apple-interchange-newline"><div class=""><div dir="ltr" class="">To answer more precisely this request (which remains valid no matter the protocol hierarchy). I propose<div class=""><br class=""></div><div class="">"matchesSequence" ( or simply "matches" or "match", whatever is more coherent with the naming guidelines).</div><div class=""><br class=""></div><div class="">So</div><div class="">var a: [Int] = [1,2,3]</div><div class="">a.matchesSequence([1,2,3]) returns true.</div><div class=""><br class=""></div><div class="">I first thought that the verb "matching" was too heavily associated to regular expressions, but i think that it's the correct equivalent for something as general as a sequence.</div><div class=""><br class=""></div><div class=""><br class=""></div><div class=""><br class=""></div><div class=""><br class=""></div><div class=""><br class=""></div><div class=""><br class=""></div></div><div class="gmail_extra"><br class=""><div class="gmail_quote">On Fri, Oct 13, 2017 at 1:24 AM, Xiaodi Wu via swift-evolution <span dir="ltr" class=""><<a href="mailto:swift-evolution@swift.org" target="_blank" class="">swift-evolution@swift.org</a>></span> wrote:<br class=""><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr" class=""><h1 class="">Rename <code class="">Sequence.elementsEqual</code></h1>
<ul class=""><li class="">Proposal: <a href="https://gist.github.com/xwu/NNNN-rename-elements-equal.md" target="_blank" class="">SE-NNNN</a></li><li class="">Authors: <a href="https://github.com/xwu" target="_blank" class="">Xiaodi Wu</a></li><li class="">Review Manager: TBD</li><li class="">Status: <strong class="">Awaiting review</strong></li></ul><h2 class=""><a href="https://gist.github.com/xwu/1f0ef4e18a7f321f22ca65a2f56772f6#introduction" class="m_2762727181953316915gmail-anchor" id="m_2762727181953316915gmail-user-content-introduction" target="_blank"></a>Introduction</h2><p class="">The current behavior of <code class="">Sequence.elementsEqual</code> 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 <code class="">Sequence.<wbr class="">lexicographicallyEquals</code>.</p>
<h2 class=""><a href="https://gist.github.com/xwu/1f0ef4e18a7f321f22ca65a2f56772f6#motivation" class="m_2762727181953316915gmail-anchor" id="m_2762727181953316915gmail-user-content-motivation" target="_blank"></a>Motivation</h2><p class=""><a href="https://twitter.com/olebegemann/status/916291785185529857" target="_blank" class="">As outlined by Ole Begemann</a>, use of <code class="">Sequence.elementsEqual(_:)</code> can lead to surprising results if the sequences compared are unordered:</p>
<div class="m_2762727181953316915gmail-highlight m_2762727181953316915gmail-highlight-source-swift"><pre class=""><span class="m_2762727181953316915gmail-pl-k">var</span> set1<span class="m_2762727181953316915gmail-pl-k">:</span> <span class="m_2762727181953316915gmail-pl-c1">Set</span><span class="m_2762727181953316915gmail-pl-k"><</span><span class="m_2762727181953316915gmail-pl-c1">Int</span><span class="m_2762727181953316915gmail-pl-k">></span> <span class="m_2762727181953316915gmail-pl-k">=</span> <span class="m_2762727181953316915gmail-pl-c1">Set</span>(<span class="m_2762727181953316915gmail-pl-c1">1</span><span class="m_2762727181953316915gmail-pl-k">...</span><span class="m_2762727181953316915gmail-pl-c1">5</span>)
<span class="m_2762727181953316915gmail-pl-k">var</span> set2<span class="m_2762727181953316915gmail-pl-k">:</span> <span class="m_2762727181953316915gmail-pl-c1">Set</span><span class="m_2762727181953316915gmail-pl-k"><</span><span class="m_2762727181953316915gmail-pl-c1">Int</span><span class="m_2762727181953316915gmail-pl-k">></span> <span class="m_2762727181953316915gmail-pl-k">=</span> <span class="m_2762727181953316915gmail-pl-c1">Set</span>((<span class="m_2762727181953316915gmail-pl-c1">1</span><span class="m_2762727181953316915gmail-pl-k">...</span><span class="m_2762727181953316915gmail-pl-c1">5</span>).<span class="m_2762727181953316915gmail-pl-c1">reversed</span>())
set1 <span class="m_2762727181953316915gmail-pl-k">==</span> set2 <span class="m_2762727181953316915gmail-pl-c"><span class="m_2762727181953316915gmail-pl-c">//</span> true</span>
<span class="m_2762727181953316915gmail-pl-c"></span>set1.<span class="m_2762727181953316915gmail-pl-c1">elementsEqual</span>(set2) <span class="m_2762727181953316915gmail-pl-c"><span class="m_2762727181953316915gmail-pl-c">//</span> false</span></pre></div><p class="">This result does reflect the <strong class="">intended and documented</strong> behavior of the <code class="">elementsEqual(_:)</code> method, which performs a <strong class="">lexicographical</strong> elementwise comparison. That is, the method first compares <code class="">set1.first</code> to <code class="">set2.first</code>, then (if the two elements compare equal) compares the next element stored internally in <code class="">set1</code> to the next element stored internally in <code class="">set2</code>, and so on.</p><p class="">In almost all circumstances where a set is compared to another set,
or a dictionary is compared to another dictionary, users should use <code class="">==</code> instead of <code class="">elementsEqual(_:)</code>.</p>
<h2 class=""><a href="https://gist.github.com/xwu/1f0ef4e18a7f321f22ca65a2f56772f6#proposed-solution" class="m_2762727181953316915gmail-anchor" id="m_2762727181953316915gmail-user-content-proposed-solution" target="_blank"></a>Proposed solution</h2><p class="">The proposed solution is the result of an iterative process of reasoning, presented here:</p><p class="">The first and most obvious solution is to remove the <code class="">elementsEqual(_:)</code> method altogether in favor of <code class="">==</code>. This prevents its misuse. However, because <code class="">elementsEqual(_:)</code> is a generic method on <code class="">Sequence</code>, we can use it to compare an instance of <code class="">UnsafeBufferPointer<Int></code> to an instance of <code class="">[Int]</code>. This is a useful and non-redundant feature which would be eliminated if the method is removed altogether.</p><p class=""><a href="https://github.com/apple/swift/pull/12318" target="_blank" class="">A second solution</a> is to create overloads that forbid the use of the <code class="">elementsEqual(_:)</code>
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.</p><p 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 <code class="">first</code> and <code class="">elementsEqual(_:)</code>.
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:</p>
<ul class=""><li class="">Finite versus infinite</li><li class="">Single-pass versus multi-pass</li><li class="">Ordered versus unordered</li><li class="">Lazy versus eager</li><li class="">Forward/bidirectional/random-<wbr class="">access</li></ul><p class="">A fourth solution is proposed here. It is predicated on the following observation:</p><p class=""><em class="">Another method similar to <code class="">elementsEqual(_:)</code> already exists on <code class="">Sequence</code> named <code class="">lexicographicallyPrecedes(_:)</code>. Like <code class="">first</code>, <code class="">elementsEqual(_:)</code>, <code class="">drop(while:)</code>,
and others, it relies on the internal order of elements in a manner
that is not completely suitable for an unordered collection. However,
like <code class="">first</code> and unlike <code class="">elementsEqual(_:)</code>, this fact is called out in the name of the method; unsurprisingly, like <code class="">first</code> and unlike <code class="">elementsEqual(_:)</code>, there is no evidence that <code class="">lexicographicallyPrecedes(_:)</code> has been a pitfall for users.</em></p><p class="">This observation suggests that a major reason for confusion over <code class="">elementsEqual(_:)</code> stems from its name. So, <strong class="">it is proposed that <code class="">elementsEqual(_:)</code> should be renamed to <code class="">lexicographicallyEquals(_:)</code></strong>.
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.</p>
<h2 class=""><a href="https://gist.github.com/xwu/1f0ef4e18a7f321f22ca65a2f56772f6#detailed-design" class="m_2762727181953316915gmail-anchor" id="m_2762727181953316915gmail-user-content-detailed-design" target="_blank"></a>Detailed design</h2>
<div class="m_2762727181953316915gmail-highlight m_2762727181953316915gmail-highlight-source-swift"><pre class=""><span class="m_2762727181953316915gmail-pl-k">extension</span> <span class="m_2762727181953316915gmail-pl-en"><span class="m_2762727181953316915gmail-pl-c1">Sequence</span></span> <span class="m_2762727181953316915gmail-pl-k">where</span> <span class="m_2762727181953316915gmail-pl-c1">Element</span> <span class="m_2762727181953316915gmail-pl-k">:</span> <span class="m_2762727181953316915gmail-pl-e"><span class="m_2762727181953316915gmail-pl-c1">Equatable</span></span> {
<span class="m_2762727181953316915gmail-pl-k">@available</span>(<span class="m_2762727181953316915gmail-pl-k">*</span>, <span class="m_2762727181953316915gmail-pl-k">deprecated</span>, <span class="m_2762727181953316915gmail-pl-k">message</span>: <span class="m_2762727181953316915gmail-pl-s"><span class="m_2762727181953316915gmail-pl-pds">"</span>Use '==' if possible to compare two sequences of the same type, or use 'lexicographicallyEquals' to compare two ordered sequences.<span class="m_2762727181953316915gmail-pl-pds">"</span></span>)
<span class="m_2762727181953316915gmail-pl-k">public</span> <span class="m_2762727181953316915gmail-pl-k">func</span> <span class="m_2762727181953316915gmail-pl-en">elementsEqual</span><<span class="m_2762727181953316915gmail-pl-c1">Other</span> : <span class="m_2762727181953316915gmail-pl-e"><span class="m_2762727181953316915gmail-pl-c1">Sequence</span></span>>(
<span class="m_2762727181953316915gmail-pl-en">_</span> <span class="m_2762727181953316915gmail-pl-smi">other</span>: Other
) <span class="m_2762727181953316915gmail-pl-k">-></span> <span class="m_2762727181953316915gmail-pl-c1">Bool</span> <span class="m_2762727181953316915gmail-pl-k">where</span> Other.<span class="m_2762727181953316915gmail-pl-c1">Element</span> <span class="m_2762727181953316915gmail-pl-k">==</span> <span class="m_2762727181953316915gmail-pl-c1">Element</span> {
<span class="m_2762727181953316915gmail-pl-k">return</span> <span class="m_2762727181953316915gmail-pl-c1">lexicographicallyEquals</span>(other)
}
<span class="m_2762727181953316915gmail-pl-k">public</span> <span class="m_2762727181953316915gmail-pl-k">func</span> <span class="m_2762727181953316915gmail-pl-en">lexicographicallyEquals</span><<span class="m_2762727181953316915gmail-pl-c1">Other</span> : <span class="m_2762727181953316915gmail-pl-e"><span class="m_2762727181953316915gmail-pl-c1">Sequence</span></span>>(
<span class="m_2762727181953316915gmail-pl-en">_</span> <span class="m_2762727181953316915gmail-pl-smi">other</span>: Other
) <span class="m_2762727181953316915gmail-pl-k">-></span> <span class="m_2762727181953316915gmail-pl-c1">Bool</span> <span class="m_2762727181953316915gmail-pl-k">where</span> Other.<span class="m_2762727181953316915gmail-pl-c1">Element</span> <span class="m_2762727181953316915gmail-pl-k">==</span> <span class="m_2762727181953316915gmail-pl-c1">Element</span> {
<span class="m_2762727181953316915gmail-pl-c"><span class="m_2762727181953316915gmail-pl-c">//</span> The body of this method is unchanged.</span>
<span class="m_2762727181953316915gmail-pl-c"></span> <span class="m_2762727181953316915gmail-pl-k">var</span> iter1 <span class="m_2762727181953316915gmail-pl-k">=</span> <span class="m_2762727181953316915gmail-pl-c1">self</span>.<span class="m_2762727181953316915gmail-pl-c1">makeIterator</span>()
<span class="m_2762727181953316915gmail-pl-k">var</span> iter2 <span class="m_2762727181953316915gmail-pl-k">=</span> other.<span class="m_2762727181953316915gmail-pl-c1">makeIterator</span>()
<span class="m_2762727181953316915gmail-pl-k">while</span> <span class="m_2762727181953316915gmail-pl-c1">true</span> {
<span class="m_2762727181953316915gmail-pl-k">switch</span> (iter1.<span class="m_2762727181953316915gmail-pl-c1">next</span>(), iter2.<span class="m_2762727181953316915gmail-pl-c1">next</span>()) {
<span class="m_2762727181953316915gmail-pl-k">case</span> <span class="m_2762727181953316915gmail-pl-k">let</span> (e1<span class="m_2762727181953316915gmail-pl-k">?</span>, e2<span class="m_2762727181953316915gmail-pl-k">?</span>)<span class="m_2762727181953316915gmail-pl-k">:</span>
<span class="m_2762727181953316915gmail-pl-k">if</span> e1 <span class="m_2762727181953316915gmail-pl-k">!=</span> e2 { <span class="m_2762727181953316915gmail-pl-k">return</span> <span class="m_2762727181953316915gmail-pl-c1">false</span> }
<span class="m_2762727181953316915gmail-pl-k">case</span> (<span class="m_2762727181953316915gmail-pl-c1">_</span><span class="m_2762727181953316915gmail-pl-k">?</span>, <span class="m_2762727181953316915gmail-pl-c1">nil</span>), (<span class="m_2762727181953316915gmail-pl-c1">nil</span>, <span class="m_2762727181953316915gmail-pl-c1">_</span><span class="m_2762727181953316915gmail-pl-k">?</span>)<span class="m_2762727181953316915gmail-pl-k">:</span>
<span class="m_2762727181953316915gmail-pl-k">return</span> <span class="m_2762727181953316915gmail-pl-c1">false</span>
<span class="m_2762727181953316915gmail-pl-k">case</span> (<span class="m_2762727181953316915gmail-pl-c1">nil</span>, <span class="m_2762727181953316915gmail-pl-c1">nil</span>)<span class="m_2762727181953316915gmail-pl-k">:</span>
<span class="m_2762727181953316915gmail-pl-k">return</span> <span class="m_2762727181953316915gmail-pl-c1">true</span>
}
}
}
}</pre></div><p class="">A parallel change will be made with respect to <code class="">elementsEqual(_:by:)</code>; that is, it will be deprecated in favor of <code class="">lexicographicallyEquals(_:by:)</code><wbr class="">.</p>
<h2 class=""><a href="https://gist.github.com/xwu/1f0ef4e18a7f321f22ca65a2f56772f6#source-compatibility" class="m_2762727181953316915gmail-anchor" id="m_2762727181953316915gmail-user-content-source-compatibility" target="_blank"></a>Source compatibility</h2><p class="">Existing code that uses <code class="">elementsEqual</code> will gain a deprecation warning.</p>
<h2 class=""><a href="https://gist.github.com/xwu/1f0ef4e18a7f321f22ca65a2f56772f6#effect-on-abi-stability" class="m_2762727181953316915gmail-anchor" id="m_2762727181953316915gmail-user-content-effect-on-abi-stability" target="_blank"></a>Effect on ABI stability</h2><p class="">None.</p>
<h2 class=""><a href="https://gist.github.com/xwu/1f0ef4e18a7f321f22ca65a2f56772f6#effect-on-api-resilience" class="m_2762727181953316915gmail-anchor" id="m_2762727181953316915gmail-user-content-effect-on-api-resilience" target="_blank"></a>Effect on API resilience</h2><p class="">This proposal adds new methods to the public API of <code class="">Sequence</code> and conforming types.</p>
<h2 class=""><a href="https://gist.github.com/xwu/1f0ef4e18a7f321f22ca65a2f56772f6#alternatives-considered" class="m_2762727181953316915gmail-anchor" id="m_2762727181953316915gmail-user-content-alternatives-considered" target="_blank"></a>Alternatives considered</h2><p class="">It is to be noted that <code class="">lexicographicallyPrecedes(_:<wbr class="">by:)</code> and <code class="">elementsEqual(_:by:)</code>
are essentially the same method, since both perform a lexicographical
comparison using a custom predicate. However, there is not a good
unifying name. (<code class="">lexicographicallyCompares(to:<wbr class="">by:)</code> 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, <code class="">elementsEqual(_:by:)</code> will be renamed <code class="">lexicographicallyEquals(_:by:)</code> as detailed above.</p></div>
<br class="">______________________________<wbr 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" rel="noreferrer" target="_blank" class="">https://lists.swift.org/<wbr class="">mailman/listinfo/swift-<wbr class="">evolution</a><br class="">
<br class=""></blockquote></div><br class=""></div>
_______________________________________________<br class="">swift-evolution mailing list<br class=""><a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a><br class="">https://lists.swift.org/mailman/listinfo/swift-evolution<br class=""></div></blockquote></div><br class=""></body></html>