Add an all algorithm to Sequence

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

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&gt;
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.

14 Likes

I like it.

l8r
Sean

···

On Mar 31, 2017, at 10:28 AM, Ben Cohen via swift-evolution <swift-evolution@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

Add an all algorithm to Sequence

  â€˘ Proposal: SE-NNNN
  â€˘ Authors: Ben Cohen
  â€˘ 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@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

Nice addition!

What do you think of equal parameter named to are?

nums.all(equal: 9)

nums.all(are: 9)

I think it reads better and adds an explicit action of what is being
checked.

···

if nums.all(are: 9) { print("all elements are 9") }

On Fri, Mar 31, 2017 at 9:28 AM, Ben Cohen via swift-evolution < swift-evolution@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/9a778e904c9be8a3692edd19bb757b
23c54aacbe/proposals/0162-all-algorithm.md

Add an all algorithm to Sequence

   - Proposal: SE-NNNN
   - Authors: Ben Cohen <https://github.com/airspeedswift&gt;
   - 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@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

--
Joshua Alvarado
alvaradojoshua0@gmail.com

1 Like

I really like this proposal. This is one of the first extensions I add to a new Swift project. I think if we’re going to add `all`, we should consider adding `none` as well. `none` can be used currently as `!contains`, but sometimes boolean logic like that can be hard to follow.

Soroush

···

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

Add anallalgorithm toSequence
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 toSequence.

Motivation

You can achieve this in Swift 3 withcontainsby 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 realizecontainscan be used this way, so may hand-roll their ownforloop, which could be buggy, or compose other inefficient alternatives:

// misses opportunity to bail earlynums.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 onSequencewhich test every element and returntrueif they match:

nums.all(equal:9) nums.all(match: isOdd)
Detailed design

Add the following extensions toSequence:

extensionSequence{/// Returns a Boolean value indicating whether every element of the sequence/// satisfies the given predicate.funcall(match criteria:(Iterator.Element)throws->Bool)rethrows->Bool}extensionSequencewhereIterator.Element:Equatable{/// Returns a Boolean value indicating whether every element of the sequence/// equals the given element.funcall(equalelement: 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.

2 Likes

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@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

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&gt;
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@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

1 Like

+1 to adding, but the name `all` suggests (to me) the return of another sequence, not a Bool.

Perhaps the function name should be question-like?

Suggesting: `membersSatisfy(condition:)` or `allSatisfy(condition:)` or maybe even just `satisfies(condition:)`
The question-like modifier/verb is necessary to suggest a Bool and IMO not a needless word.

Regards,
Will Stanton

···

On Mar 31, 2017, at 11:28, Ben Cohen via swift-evolution <swift-evolution@swift.org> wrote:

Hopefully non-controversial, aside from the naming of the method and arguments, about which controversy abounds

2 Likes

Agree, this is a nice addition as-is.

···

On Fri, Mar 31, 2017 at 10:42 AM, Sean Heber via swift-evolution < swift-evolution@swift.org> wrote:

I like it.

l8r
Sean

> On Mar 31, 2017, at 10:28 AM, Ben Cohen via swift-evolution < > swift-evolution@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/9a778e904c9be8a3692edd19bb757b
23c54aacbe/proposals/0162-all-algorithm.md
>
>
> Add an all algorithm to Sequence
>
> • Proposal: SE-NNNN
> • Authors: Ben Cohen
> • 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@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

Nice addition!

What do you think of equal parameter named to are?

nums.all(equal: 9)

nums.all(are: 9)

I think it reads better and adds an explicit action of what is being
checked.

if nums.all(are: 9) { print("all elements are 9") }

By the same token, `all(match:)` could be renamed `all(are:)`, and therein
lies the problem.
I like `equal`. It explains what operation is being performed to determine
if two things "are" the same and distinguishes the function from `match`.

···

On Fri, Mar 31, 2017 at 12:14 PM, Joshua Alvarado via swift-evolution < swift-evolution@swift.org> wrote:

On Fri, Mar 31, 2017 at 9:28 AM, Ben Cohen via swift-evolution < > swift-evolution@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: airsp · GitHub
eedswift/swift-evolution/blob/9a778e904c9be8a3692edd19bb757b
23c54aacbe/proposals/0162-all-algorithm.md

Add an all algorithm to Sequence

   - Proposal: SE-NNNN
   - Authors: Ben Cohen <https://github.com/airspeedswift&gt;
   - 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@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

--
Joshua Alvarado
alvaradojoshua0@gmail.com

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

1 Like

I agree. But I don’t think the predicate needs an argument label.

`membersSatisfy(_:)` or `forAll(_:)` sounds better.

-Richard

···

On Mar 31, 2017, at 23:02, Will Stanton via swift-evolution <swift-evolution@swift.org> wrote:

+1 to adding, but the name `all` suggests (to me) the return of another sequence, not a Bool.

Perhaps the function name should be question-like?

Suggesting: `membersSatisfy(condition:)` or `allSatisfy(condition:)` or maybe even just `satisfies(condition:)`
The question-like modifier/verb is necessary to suggest a Bool and IMO not a needless word.

Regards,
Will Stanton

On Mar 31, 2017, at 11:28, Ben Cohen via swift-evolution <swift-evolution@swift.org> wrote:

Hopefully non-controversial, aside from the naming of the method and arguments, about which controversy abounds

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

+1 to adding, but the name `all` suggests (to me) the return of another sequence, not a Bool.

I'm not too concerned because the mandatory labels makes it clear.

···

On 1 Apr 2017, at 06:02, Will Stanton via swift-evolution <swift-evolution@swift.org> wrote:

Perhaps the function name should be question-like?

Suggesting: `membersSatisfy(condition:)` or `allSatisfy(condition:)` or maybe even just `satisfies(condition:)`
The question-like modifier/verb is necessary to suggest a Bool and IMO not a needless word.

Regards,
Will Stanton

On Mar 31, 2017, at 11:28, Ben Cohen via swift-evolution <swift-evolution@swift.org> wrote:

Hopefully non-controversial, aside from the naming of the method and arguments, about which controversy abounds

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

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@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@swift.org <mailto:swift-evolution@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

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&gt;
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@swift.org <mailto: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

1 Like

For “all(equal:)” I think there should be no argument label. We can already
write “nums.contains(9)”, so if we add “all” then we should be able to
write “nums.all(9)”.

Other than that, I like the idea.

Nevin

Nice, would be good to see this added. Surprised this doesn’t exist already, tbh.

···

On 31 Mar 2017, at 16:48, Xiaodi Wu via swift-evolution <swift-evolution@swift.org> wrote:

Agree, this is a nice addition as-is.

On Fri, Mar 31, 2017 at 10:42 AM, Sean Heber via swift-evolution <swift-evolution@swift.org> wrote:
I like it.

l8r
Sean

> On Mar 31, 2017, at 10:28 AM, Ben Cohen via swift-evolution <swift-evolution@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
>
>
> Add an all algorithm to Sequence
>
> • Proposal: SE-NNNN
> • Authors: Ben Cohen
> • 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@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

I agree that based on the method name, I thought a collection would be
returned.

···

On Sat, Apr 1, 2017 at 12:36 AM, David Hart via swift-evolution < swift-evolution@swift.org> wrote:

> On 1 Apr 2017, at 06:02, Will Stanton via swift-evolution < > swift-evolution@swift.org> wrote:
>
> +1 to adding, but the name `all` suggests (to me) the return of another
sequence, not a Bool.

I'm not too concerned because the mandatory labels makes it clear.

> Perhaps the function name should be question-like?
>
> Suggesting: `membersSatisfy(condition:)` or `allSatisfy(condition:)` or
maybe even just `satisfies(condition:)`
> The question-like modifier/verb is necessary to suggest a Bool and IMO
not a needless word.
>
> Regards,
> Will Stanton
>
>> On Mar 31, 2017, at 11:28, Ben Cohen via swift-evolution < > swift-evolution@swift.org> wrote:
>>
>> Hopefully non-controversial, aside from the naming of the method and
arguments, about which controversy abounds
>
> _______________________________________________
> 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

--
Brandon

I agree that based on the method name, I thought a collection would be returned.

Now that I think more about it, I think you're right. It is confusing. Perhaps:

allAre(equalTo: )
allAre(matching: )

···

On 1 Apr 2017, at 09:50, Brandon Trussell <brandon2k3@gmail.com> wrote:

On Sat, Apr 1, 2017 at 12:36 AM, David Hart via swift-evolution <swift-evolution@swift.org> wrote:

> On 1 Apr 2017, at 06:02, Will Stanton via swift-evolution <swift-evolution@swift.org> wrote:
>
> +1 to adding, but the name `all` suggests (to me) the return of another sequence, not a Bool.

I'm not too concerned because the mandatory labels makes it clear.

> Perhaps the function name should be question-like?
>
> Suggesting: `membersSatisfy(condition:)` or `allSatisfy(condition:)` or maybe even just `satisfies(condition:)`
> The question-like modifier/verb is necessary to suggest a Bool and IMO not a needless word.
>
> Regards,
> Will Stanton
>
>> On Mar 31, 2017, at 11:28, Ben Cohen via swift-evolution <swift-evolution@swift.org> wrote:
>>
>> Hopefully non-controversial, aside from the naming of the method and arguments, about which controversy abounds
>
> _______________________________________________
> 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

--
Brandon

1 Like

I agree. But I don’t think the predicate needs an argument label.

`membersSatisfy(_:)` or `forAll(_:)` sounds better.

checkAll(areEqualTo:) ?

···

On 01.04.2017 9:17, Richard Wei via swift-evolution wrote:

-Richard

On Mar 31, 2017, at 23:02, Will Stanton via swift-evolution <swift-evolution@swift.org> wrote:

+1 to adding, but the name `all` suggests (to me) the return of another sequence, not a Bool.

Perhaps the function name should be question-like?

Suggesting: `membersSatisfy(condition:)` or `allSatisfy(condition:)` or maybe even just `satisfies(condition:)`
The question-like modifier/verb is necessary to suggest a Bool and IMO not a needless word.

Regards,
Will Stanton

On Mar 31, 2017, at 11:28, Ben Cohen via swift-evolution <swift-evolution@swift.org> wrote:

Hopefully non-controversial, aside from the naming of the method and arguments, about which controversy abounds

_______________________________________________
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

I agree that based on the method name, I thought a collection would be
returned.

From the other side, for example C# has the similar IEnumerable.All() method which "Determines whether all elements of a sequence satisfy a condition."

···

On 01.04.2017 10:50, Brandon Trussell via swift-evolution wrote:

On Sat, Apr 1, 2017 at 12:36 AM, David Hart via swift-evolution > <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

    > On 1 Apr 2017, at 06:02, Will Stanton via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:
    >
    > +1 to adding, but the name `all` suggests (to me) the return of another sequence, not a Bool.

    I'm not too concerned because the mandatory labels makes it clear.

    > Perhaps the function name should be question-like?
    >
    > Suggesting: `membersSatisfy(condition:)` or `allSatisfy(condition:)`
    or maybe even just `satisfies(condition:)`
    > The question-like modifier/verb is necessary to suggest a Bool and
    IMO not a needless word.
    >
    > Regards,
    > Will Stanton
    >
    >> On Mar 31, 2017, at 11:28, Ben Cohen via swift-evolution > <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:
    >>
    >> Hopefully non-controversial, aside from the naming of the method and
    arguments, about which controversy abounds
    >
    > _______________________________________________
    > swift-evolution mailing list
    > swift-evolution@swift.org <mailto:swift-evolution@swift.org>
    > https://lists.swift.org/mailman/listinfo/swift-evolution
    <https://lists.swift.org/mailman/listinfo/swift-evolution&gt;

    _______________________________________________
    swift-evolution mailing list
    swift-evolution@swift.org <mailto:swift-evolution@swift.org>
    https://lists.swift.org/mailman/listinfo/swift-evolution
    <https://lists.swift.org/mailman/listinfo/swift-evolution&gt;

--
Brandon

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

I like onlyContains() and containsOnly() so far.

···

On Mon, Apr 3, 2017 at 1:29 AM, Daniel Duan via swift-evolution < swift-evolution@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@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@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/9a778e904c9be8a3692edd19bb757b
23c54aacbe/proposals/0162-all-algorithm.md

Add an all algorithm to Sequence

   - Proposal: SE-NNNN
   - Authors: Ben Cohen <https://github.com/airspeedswift&gt;
   - 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@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

--
Brandon

1 Like

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@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@swift.org <mailto:swift-evolution@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@swift.org <mailto:swift-evolution@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

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&gt;
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@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto: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

+1

···

Am 03.04.2017 um 10:29 schrieb Daniel Duan via swift-evolution <swift-evolution@swift.org>:

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@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@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

Add an all algorithm to Sequence
Proposal: SE-NNNN
Authors: Ben Cohen
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

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution