Skip to content

Latest commit

 

History

History
66 lines (49 loc) · 2.29 KB

0032-sequencetype-find.md

File metadata and controls

66 lines (49 loc) · 2.29 KB

Add find method to Sequence

Introduction

Add a new extension method to Sequence called find() that returns the found element.

Swift-evolution thread: Proposal: Add function SequenceType.find()

Motivation

It's often useful to find the first element of a sequence that passes some given predicate. For Collections you can call index(of:) or index(where:) and pass the resulting index back into the subscript, but this is a bit awkward. For Sequences, there's no easy way to do this besides a manual loop that doesn't require filtering the entire sequence and producing an array.

I have seen people write code like seq.lazy.filter(predicate).first, but this doesn't actually work lazily because .first is only a method on Collection, which means the call to filter() ends up resolving to the Sequence.filter() that returns an Array instead of to LazySequenceProtocol.filter() that returns a lazy sequence. Users typically aren't aware of this, which means they end up doing a lot more work than expected.

Proposed solution

Extend Sequence with a method called find() that takes a predicate and returns an optional value of the first element that passes the predicate, if any.

Detailed design

Add the following extension to Sequence:

extension Sequence {
  /// Returns the first element where `predicate` returns `true`, or `nil`
  /// if such value is not found.
  public func find( _ predicate: @noescape (Self.Iterator.Element) throws -> Bool) rethrows -> Self.Iterator.Element? {
    for elt in self {
      if try predicate(elt) {
        return elt
      }
    }
    return nil
  }
}

Impact on existing code

None, this feature is purely additive.

In theory, we might provide an automatic conversion from seq.filter(predicate).first or seq.lazy.filter(predicate).first to seq.find(predicate), although the existing code would continue to compile just fine.

Alternatives considered

None