[swift-evolution] [Pitch] Add an all algorithm to Sequence

David Rönnqvist david.ronnqvist at gmail.com
Tue Apr 4 04:16:33 CDT 2017


I agree that  `all(equal:)` and `all(match:)` are really good names for these methods (I could also consider `every`).

In my understanding of the Swift API Design Guidelines, it’s good for a number of reasons:

It omits needless words. It’s a sequence of Element, so explicitly mentioning “elements”, “members”, or “items" doesn’t add much.

It strives for fluent usage when used with their argument labels. As Daniel Duan pointed out, these names roughly read read as:

> things all match condition?
> things all equal value?


Without the argument label it’s not as clear what it does, but other functions have a similar problems when used without argument labels. For example, 

xs.prefix { $0 > 5 }
xs.drop { $0 > 5 }
xs.index { $0 > 5 }

It uses terminology well, if `all` is accepted as a term of art. It is at least a common term in other languages for this functionality. 

However, one area where it doesn’t hold as well (ignoring any term of art argument) is that Boolean methods [...] should read as assertions […] when the use is nonmutating. Here I kind of like the `are` prefix, similar to how `empty` has an `is` prefix (isEmpty). In this case I would also like to see the labels change for a more fluent usage: `areAll(equalTo:)` and `areAll(matching:)`.


> On 3 Apr 2017, at 10:29, Daniel Duan via swift-evolution <swift-evolution at swift.org> wrote:
> 
> I want to retract my nitpickings on argument labels; `all(equal:)` and `all(match:)` are the best names for these methods.
> 
> things all match condition?
> things all equal value?
> 
> If we accept `all` as a term of art (which I think we should), along with these labels the use site are very readable!
> 
>> On Mar 31, 2017, at 6:38 PM, Daniel Duan via swift-evolution <swift-evolution at swift.org <mailto:swift-evolution at swift.org>> wrote:
>> 
>> nit: should these names be `all(matching)`/`all(equalTo)` per API Design Guidelines?
>>> On Mar 31, 2017, at 8:28 AM, Ben Cohen via swift-evolution <swift-evolution at swift.org <mailto:swift-evolution at swift.org>> wrote:
>>> 
>>> Hi,
>>> 
>>> A short proposal for you as part of the algorithms theme. Hopefully non-controversial, aside from the naming of the method and arguments, about which controversy abounds. Online copy here: https://github.com/airspeedswift/swift-evolution/blob/9a778e904c9be8a3692edd19bb757b23c54aacbe/proposals/0162-all-algorithm.md <https://github.com/airspeedswift/swift-evolution/blob/9a778e904c9be8a3692edd19bb757b23c54aacbe/proposals/0162-all-algorithm.md>
>>> 
>>> 
>>> Add an all algorithm to Sequence
>>> 
>>> Proposal: SE-NNNN <file:///Users/ben_cohen/Documents/swift-evolution/proposals/0162-all-algorithm.md>
>>> Authors: Ben Cohen <https://github.com/airspeedswift>
>>> Review Manager: TBD
>>> Status: Awaiting review
>>> Introduction
>>> 
>>> It is common to want to confirm that every element of a sequence equals a value, or matches a certain criteria. Many implementations of this can be found in use on github. This proposal adds such a method to Sequence.
>>> 
>>> Motivation
>>> 
>>> You can achieve this in Swift 3 with contains by negating both the criteria and the result:
>>> 
>>> // every element is 9
>>> !nums.contains { $0 != 9 }
>>> // every element is odd
>>> !nums.contains { !isOdd($0) }
>>> but these are a readability nightmare. Additionally, developers may not make the leap to realize contains can be used this way, so may hand-roll their own for loop, which could be buggy, or compose other inefficient alternatives:
>>> 
>>> // misses opportunity to bail early
>>> nums.reduce(true) { $0.0 && $0.1 == 9 }
>>> // the most straw-man travesty I could think of...
>>> Set(nums).count == 1 && Set(nums).first == 9
>>> Proposed solution
>>> 
>>> Introduce two algorithms on Sequence which test every element and return true if they match:
>>> 
>>> nums.all(equal: 9)
>>> nums.all(match: isOdd)
>>> Detailed design
>>> 
>>> Add the following extensions to Sequence:
>>> 
>>> extension Sequence {
>>>   /// Returns a Boolean value indicating whether every element of the sequence
>>>   /// satisfies the given predicate.
>>>   func all(match criteria: (Iterator.Element) throws -> Bool) rethrows -> Bool
>>> }
>>> 
>>> extension Sequence where Iterator.Element: Equatable {
>>>   /// Returns a Boolean value indicating whether every element of the sequence
>>>   /// equals the given element.
>>>   func all(equal element: Iterator.Element) -> Bool
>>> }
>>> Source compatibility
>>> 
>>> This change is purely additive so has no source compatibility consequences.
>>> 
>>> Effect on ABI stability
>>> 
>>> This change is purely additive so has no ABI stability consequences.
>>> 
>>> Effect on API resilience
>>> 
>>> This change is purely additive so has no API resilience consequences.
>>> 
>>> Alternatives considered
>>> 
>>> Not adding it.
>>> _______________________________________________
>>> swift-evolution mailing list
>>> swift-evolution at swift.org <mailto:swift-evolution at swift.org>
>>> https://lists.swift.org/mailman/listinfo/swift-evolution <https://lists.swift.org/mailman/listinfo/swift-evolution>
>> 
>> _______________________________________________
>> swift-evolution mailing list
>> swift-evolution at swift.org <mailto:swift-evolution at swift.org>
>> https://lists.swift.org/mailman/listinfo/swift-evolution
> 
> _______________________________________________
> swift-evolution mailing list
> swift-evolution at swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20170404/32a1e3d8/attachment-0001.html>


More information about the swift-evolution mailing list