Protocol

# LazySequenceProtocol

A sequence on which normally-eager sequence operations are implemented lazily.

``protocol LazySequenceProtocol : Sequence``

Lazy sequences can be used to avoid needless storage allocation and computation, because they use an underlying sequence for storage and compute their elements on demand. For example, `doubled` in this code sample is a sequence containing the values `2`, `4`, and `6`.

``let doubled = [1, 2, 3].lazy.map { \$0 * 2 }``

Each time an element of the lazy sequence `doubled` is accessed, the closure accesses and transforms an element of the underlying array.

Sequence operations that take closure arguments, such as `map(_:)` and `filter(_:)`, are normally eager: They use the closure immediately and return a new array. When you use the `lazy` property, you give the standard library explicit permission to store the closure and the sequence in the result, and defer computation until it is needed.

To add a new lazy sequence operation, extend this protocol with a method that returns a lazy wrapper that itself conforms to `LazySequenceProtocol`. For example, an eager `scan(_:_:)` method is defined as follows:

``````extension Sequence {
/// Returns an array containing the results of
///
///   p.reduce(initial, nextPartialResult)
///
/// for each prefix `p` of `self`, in order from shortest to
/// longest. For example:
///
///     (1..<6).scan(0, +) // [0, 1, 3, 6, 10, 15]
///
/// - Complexity: O(n)
func scan<Result>(
_ initial: Result,
_ nextPartialResult: (Result, Element) -> Result
) -> [Result] {
var result = [initial]
for x in self {
result.append(nextPartialResult(result.last!, x))
}
return result
}
}``````

You can build a sequence type that lazily computes the elements in the result of a scan:

``````struct LazyScanSequence<Base: Sequence, Result>
: LazySequenceProtocol
{
let initial: Result
let base: Base
let nextPartialResult:
(Result, Base.Element) -> Result

struct Iterator: IteratorProtocol {
var base: Base.Iterator
var nextElement: Result?
let nextPartialResult:
(Result, Base.Element) -> Result

mutating func next() -> Result? {
return nextElement.map { result in
nextElement = base.next().map {
nextPartialResult(result, \$0)
}
return result
}
}
}

func makeIterator() -> Iterator {
return Iterator(
base: base.makeIterator(),
nextElement: initial as Result?,
nextPartialResult: nextPartialResult)
}
}``````

Finally, you can give all lazy sequences a lazy `scan(_:_:)` method:

``````extension LazySequenceProtocol {
func scan<Result>(
_ initial: Result,
_ nextPartialResult: @escaping (Result, Element) -> Result
) -> LazyScanSequence<Self, Result> {
return LazyScanSequence(
initial: initial, base: self, nextPartialResult: nextPartialResult)
}
}``````

With this type and extension method, you can call `.lazy.scan(_:_:)` on any sequence to create a lazily computed scan. The resulting `LazyScanSequence` is itself lazy, too, so further sequence operations also defer computation.

The explicit permission to implement operations lazily applies only in contexts where the sequence is statically known to conform to `LazySequenceProtocol`. In the following example, because the extension applies only to `Sequence`, side-effects such as the accumulation of `result` are never unexpectedly dropped or deferred:

``````extension Sequence where Element == Int {
func sum() -> Int {
var result = 0
_ = self.map { result += \$0 }
return result
}
}``````

Don’t actually use `map` for this purpose, however, because it creates and discards the resulting array. Instead, use `reduce` for summing operations, or `forEach` or a `for`-`in` loop for operations with side effects.

## Supertypes

• `protocol Sequence`

## Requirements

• `associatedtype Elements : Sequence = Self`

A `Sequence` that can contain the same elements as this one, possibly with a simpler type.

• `var elements: Self.Elements`

A sequence containing the same elements as this one, possibly with a simpler type.

## Citizens in Swift

### Members

• `var lazy: LazySequence<Self.Elements>`
• `var lazy: Self.Elements`
• `func compactMap<ElementOfResult>((Self.Elements.Element) -> ElementOfResult?) -> LazyMapSequence<LazyFilterSequence<LazyMapSequence<Self.Elements, ElementOfResult?>>, ElementOfResult>`

Returns the non-`nil` results of mapping the given transformation over this sequence.

• `func drop(while: (Self.Elements.Element) -> Bool) -> LazyDropWhileSequence<Self.Elements>`

Returns a lazy sequence that skips any initial elements that satisfy `predicate`.

• `func filter((Self.Elements.Element) -> Bool) -> LazyFilterSequence<Self.Elements>`

Returns the elements of `self` that satisfy `isIncluded`.

• `func flatMap<SegmentOfResult>((Self.Elements.Element) -> SegmentOfResult) -> LazySequence<FlattenSequence<LazyMapSequence<Self.Elements, SegmentOfResult>>>`

Returns the concatenated results of mapping the given transformation over this sequence.

• `func map<U>((Self.Element) -> U) -> LazyMapSequence<Self.Elements, U>`

Returns a `LazyMapSequence` over this `Sequence`. The elements of the result are computed lazily, each time they are read, by calling `transform` function on a base element.

• `func prefix(while: (Self.Elements.Element) -> Bool) -> LazyPrefixWhileSequence<Self.Elements>`

Returns a lazy sequence of the initial consecutive elements that satisfy `predicate`.

• `func flatMap<ElementOfResult>((Self.Elements.Element) -> ElementOfResult?) -> LazyMapSequence<LazyFilterSequence<LazyMapSequence<Self.Elements, ElementOfResult?>>, ElementOfResult>`

Returns the non-`nil` results of mapping the given transformation over this sequence.

### Subtypes

• `protocol LazyCollectionProtocol`

## Citizens in Swift

`where Self.Element:Sequence`

### Members

• `func joined() -> LazySequence<FlattenSequence<Self.Elements>>`

Returns a lazy sequence that concatenates the elements of this sequence of sequences.

## Extension in Algorithms

### Members

• `func reductions((Self.Element, Self.Element) -> Self.Element) -> InclusiveReductionsSequence<Self.Elements>`

Returns a sequence containing the accumulated results of combining the elements of the sequence using the given closure.

• `func reductions<Result>(Result, (Result, Self.Element) -> Result) -> ExclusiveReductionsSequence<Self.Elements, Result>`

Returns a sequence containing the accumulated results of combining the elements of the sequence using the given closure.

• `func reductions<Result>(into: Result, (inout Result, Self.Element) -> Void) -> ExclusiveReductionsSequence<Self.Elements, Result>`

Returns a sequence containing the accumulated results of combining the elements of the sequence using the given closure.

• `func split(maxSplits: Int, omittingEmptySubsequences: Bool, whereSeparator: (Self.Element) -> Bool) -> SplitSequence<Self.Elements>`

Lazily returns the longest possible subsequences of the sequence, in order, that don’t contain elements satisfying the given predicate.

• `func uniqued<Subject>(on: (Self.Element) -> Subject) -> UniquedSequence<Self, Subject>`

Returns a lazy sequence with the unique elements of this sequence (as determined by the given projection), in the order of the first occurrence of each unique element.

• `func scan((Self.Element, Self.Element) -> Self.Element) -> InclusiveReductionsSequence<Self.Elements>`
• `func scan<Result>(Result, (Result, Self.Element) -> Result) -> ExclusiveReductionsSequence<Self.Elements, Result>`
• `func scan<Result>(into: Result, (inout Result, Self.Element) -> Void) -> ExclusiveReductionsSequence<Self.Elements, Result>`

## Extension in Algorithms

`where Self:Collection, Self.Element:Equatable, Self.Elements:Collection`

### Members

• `func split(separator: Self.Element, maxSplits: Int, omittingEmptySubsequences: Bool) -> SplitCollection<Self.Elements>`

Lazily returns the longest possible subsequences of the collection, in order, around elements equal to the given element.

## Extension in Algorithms

`where Self:Collection, Self.Elements:Collection`

### Members

• `func chunked(by: (Self.Element, Self.Element) -> Bool) -> ChunkedByCollection<Self.Elements, Self.Element>`

Returns a lazy collection of subsequences of this collection, chunked by the given predicate.

• `func chunked<Subject>(on: (Self.Element) -> Subject) -> ChunkedOnCollection<Self.Elements, Subject>`

Returns a lazy collection of subsequences of this collection, chunked by grouping elements that project to the same value.

• `func split(maxSplits: Int, omittingEmptySubsequences: Bool, whereSeparator: (Self.Element) -> Bool) -> SplitCollection<Self.Elements>`

Lazily returns the longest possible subsequences of the collection, in order, that don’t contain elements satisfying the given predicate.

## Extension in Algorithms

`where Self.Element:Equatable`

### Members

• `func split(separator: Self.Element, maxSplits: Int, omittingEmptySubsequences: Bool) -> SplitSequence<Self.Elements>`

Lazily returns the longest possible subsequences of the sequence, in order, around elements equal to the given element.

## Extension in Algorithms

`where Self.Element:Sequence`

### Members

• `func joined<Separator>(by: (Self.Element, Self.Element) -> Separator) -> JoinedByClosureSequence<Self.Elements, Separator>`

Returns the concatenation of the elements in this sequence of sequences, inserting the separator produced by the closure between each sequence.

• `func joined(by: (Self.Element, Self.Element) -> Self.Element.Element) -> JoinedByClosureSequence<Self.Elements, CollectionOfOne<Self.Element.Element>>`

Returns the concatenation of the elements in this sequence of sequences, inserting the separator produced by the closure between each sequence.

## Extension in Algorithms

`where Self.Element:Collection, Self.Elements:Collection`

### Members

• `func joined<Separator>(by: (Self.Element, Self.Element) -> Separator) -> JoinedByClosureCollection<Self.Elements, Separator>`

Returns the concatenation of the elements in this collection of collections, inserting the separator produced by the closure between each sequence.

• `func joined(by: (Self.Element, Self.Element) -> Self.Element.Element) -> JoinedByClosureCollection<Self.Elements, CollectionOfOne<Self.Element.Element>>`

Returns the concatenation of the elements in this collection of collections, inserting the separator produced by the closure between each sequence.