+1

Agree with the reasoning and that this is the best solution. It reduces the 
risk of confusing the function for what it’s not.

> On 13 Oct 2017, at 01:37, Kelvin Ma via swift-evolution 
> <swift-evolution@swift.org> wrote:
> 
> I’ve always hated the use of the word “lexicographically” in that method 1) 
> because lexicographically is hard to spell, and 2) because it’s weird to say 
> that an unordered collection has a lexicographical order. But this change is 
> probably for the best.
> 
>> On Thu, Oct 12, 2017 at 6:24 PM, Xiaodi Wu via swift-evolution 
>> <swift-evolution@swift.org> wrote:
>> Rename Sequence.elementsEqual
>> 
>> Proposal: SE-NNNN
>> Authors: Xiaodi Wu
>> Review Manager: TBD
>> Status: Awaiting review
>> Introduction
>> 
>> 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.
>> 
>> Motivation
>> 
>> As outlined by Ole Begemann, use of Sequence.elementsEqual(_:) can lead to 
>> surprising results if the sequences compared are unordered:
>> 
>> var set1: Set<Int> = Set(1...5)
>> var set2: Set<Int> = Set((1...5).reversed())
>> 
>> set1 == set2 // true
>> set1.elementsEqual(set2) // false
>> 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.
>> 
>> 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(_:).
>> 
>> Proposed solution
>> 
>> The proposed solution is the result of an iterative process of reasoning, 
>> presented here:
>> 
>> 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<Int> to an instance of [Int]. This is a 
>> useful and non-redundant feature which would be eliminated if the method is 
>> removed altogether.
>> 
>> A second solution 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.
>> 
>> 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:
>> 
>> Finite versus infinite
>> Single-pass versus multi-pass
>> Ordered versus unordered
>> Lazy versus eager
>> Forward/bidirectional/random-access
>> A fourth solution is proposed here. It is predicated on the following 
>> observation:
>> 
>> 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.
>> 
>> 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.
>> 
>> Detailed design
>> 
>> extension Sequence where Element : Equatable {
>>   @available(*, deprecated, message: "Use '==' if possible to compare two 
>> sequences of the same type, or use 'lexicographicallyEquals' to compare two 
>> ordered sequences.")
>>   public func elementsEqual<Other : Sequence>(
>>     _ other: Other
>>   ) -> Bool where Other.Element == Element {
>>     return lexicographicallyEquals(other)
>>   }
>>   
>>   public func lexicographicallyEquals<Other : Sequence>(
>>     _ other: Other
>>   ) -> Bool where Other.Element == Element {
>>     // The body of this method is unchanged.
>>     var iter1 = self.makeIterator()
>>     var iter2 = other.makeIterator()
>>     while true {
>>       switch (iter1.next(), iter2.next()) {
>>       case let (e1?, e2?):
>>         if e1 != e2 { return false }
>>       case (_?, nil), (nil, _?):
>>         return false
>>       case (nil, nil):
>>         return true
>>       }
>>     }
>>   }
>> }
>> A parallel change will be made with respect to elementsEqual(_:by:); that 
>> is, it will be deprecated in favor of lexicographicallyEquals(_:by:).
>> 
>> Source compatibility
>> 
>> Existing code that uses elementsEqual will gain a deprecation warning.
>> 
>> Effect on ABI stability
>> 
>> None.
>> 
>> Effect on API resilience
>> 
>> This proposal adds new methods to the public API of Sequence and conforming 
>> types.
>> 
>> Alternatives considered
>> 
>> 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.
>> 
>> 
>> _______________________________________________
>> swift-evolution mailing list
>> swift-evolution@swift.org
>> https://lists.swift.org/mailman/listinfo/swift-evolution
>> 
> 
> _______________________________________________
> swift-evolution mailing list
> swift-evolution@swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

Reply via email to