//===--- SequenceAlgorithms.swift.gyb -------------------------------------===// // // This source file is part of the Swift.org open source project // // Copyright (c) 2014 - 2015 Apple Inc. and the Swift project authors // Licensed under Apache License v2.0 with Runtime Library Exception // // See http://swift.org/LICENSE.txt for license information // See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors // //===----------------------------------------------------------------------===// %{ # We know we will eventually get a SequenceType.Element type. Define # a shorthand that we can use today. GElement = "Generator.Element" }% //===----------------------------------------------------------------------===// // enumerate() //===----------------------------------------------------------------------===// extension SequenceType { /// Return a lazy `SequenceType` containing pairs (*n*, *x*), where /// *n*s are consecutive `Int`s starting at zero, and *x*s are /// the elements of `base`: /// /// > for (n, c) in enumerate("Swift") { println("\(n): '\(c)'" ) } /// 0: 'S' /// 1: 'w' /// 2: 'i' /// 3: 'f' /// 4: 't' final public func _prext_enumerate() -> EnumerateSequence { return EnumerateSequence(self) } } //===----------------------------------------------------------------------===// // minElement(), maxElement() //===----------------------------------------------------------------------===// % # Generate two versions: with explicit predicates and with % # a Comparable requirement. % for preds in [ True, False ]: %{ if preds: orderingRequirement = """ /// Requires: `isOrderedBefore` is a [strict weak ordering](http://en.wikipedia.org/wiki/Strict_weak_order#Strict_weak_orderings). /// over `self`.""" else: orderingRequirement = "" }% extension SequenceType ${"" if preds else "where Self.Generator.Element : Comparable"} { /// Returns the minimum element in `self` or `nil` if the sequence is empty. /// /// - complexity: O(count(elements)) /// ${orderingRequirement} final public func _prext_minElement( % if preds: @noescape isOrderedBefore: (${GElement}, ${GElement}) -> Bool % end ) -> ${GElement}? { var g = generate() require var result = g.next() else { return nil } for e in GeneratorSequence(g) { % if preds: if isOrderedBefore(e, result) { result = e } % else: if e < result { result = e } % end } return result } /// Returns the maximum element in `self` or `nil` if the sequence is empty. /// /// - complexity: O(count(elements)) /// ${orderingRequirement} final public func _prext_maxElement( % if preds: @noescape isOrderedBefore: (${GElement}, ${GElement}) -> Bool % end ) -> ${GElement}? { var g = generate() require var result = g.next() else { return nil } for e in GeneratorSequence(g) { % if preds: if isOrderedBefore(result, e) { result = e } % else: if e > result { result = e } % end } return result } } % end //===----------------------------------------------------------------------===// // startsWith() //===----------------------------------------------------------------------===// % # Generate two versions: with explicit predicates and with % # an Equatable requirement. % for preds in [ True, False ]: extension SequenceType ${"" if preds else "where Self.Generator.Element : Equatable"} { %{ if preds: comment = """ /// Return true iff `self` begins with elements equivalent to those of /// `other`, using `isEquivalent` as the equivalence test. Return true if /// `other` is empty. /// /// Requires: `isEquivalent` is an [equivalence relation](http://en.wikipedia.org/wiki/Equivalence_relation)""" else: comment = """ /// Return true iff the the initial elements of `self` are equal to `prefix`. /// Return true if `other` is empty.""" }% ${comment} final public func _prext_startsWith< OtherSequence : SequenceType where OtherSequence.${GElement} == ${GElement} >( other: OtherSequence${"," if preds else ""} % if preds: @noescape isEquivalent: (${GElement}, ${GElement}) -> Bool % end ) -> Bool { var otherGenerator = other.generate() for e0 in self { if let e1 = otherGenerator.next() { if ${"!isEquivalent(e0, e1)" if preds else "e0 != e1"} { return false } } else { return true } } return otherGenerator.next() == nil } } % end //===----------------------------------------------------------------------===// // elementsEqual() //===----------------------------------------------------------------------===// % # Generate two versions: with explicit predicates and with % # an Equatable requirement. % for preds in [ True, False ]: extension SequenceType ${"" if preds else "where Self.Generator.Element : Equatable"} { %{ if preds: comment = """ /// Return true iff `self` and `other` contain equivalent elements, using /// `isEquivalent` as the equivalence test. /// /// Requires: `isEquivalent` is an [equivalence relation](http://en.wikipedia.org/wiki/Equivalence_relation)""" else: comment = """ /// Return `true` iff `self` and `other` contain the same elements in the /// same order.""" }% ${comment} final public func _prext_elementsEqual< OtherSequence : SequenceType where OtherSequence.${GElement} == ${GElement} >( other: OtherSequence${"," if preds else ""} % if preds: @noescape isEquivalent: (${GElement}, ${GElement}) -> Bool % end ) -> Bool { var g1 = self.generate() var g2 = other.generate() while true { switch (g1.next(), g2.next()) { case let (e1?, e2?): % if preds: if !isEquivalent(e1, e2) { % else: if e1 != e2 { % end return false } case (_?, nil), (nil, _?): return false case (nil, nil): return true } } } } % end //===----------------------------------------------------------------------===// // lexicographicalCompare() //===----------------------------------------------------------------------===// % # Generate two versions: with explicit predicates and with % # Comparable requirement. % for preds in [ True, False ]: extension SequenceType ${"" if preds else "where Self.Generator.Element : Comparable"} { %{ if preds: comment = """ /// Return true iff `self` precedes `other` in a lexicographical ("dictionary") /// ordering, using `isOrderedBefore` as the comparison between elements. /// /// - note: This method implements the mathematical notion of lexicographical /// ordering, which has no connection to Unicode. If you are sorting strings /// to present to the end-user, you should use `String` APIs that perform /// localized comparison. /// /// Requires: `isOrderedBefore` is a [strict weak ordering](http://en.wikipedia.org/wiki/Strict_weak_order#Strict_weak_orderings) /// over the elements of `self` and `other`.""" else: comment = """ /// Return true iff `self` precedes `other` in a lexicographical ("dictionary") /// ordering, using "<" as the comparison between elements. /// /// - note: This method implements the mathematical notion of lexicographical /// ordering, which has no connection to Unicode. If you are sorting strings /// to present to the end-user, you should use `String` APIs that perform /// localized comparison.""" }% ${comment} final public func _prext_lexicographicalCompare< OtherSequence : SequenceType where OtherSequence.${GElement} == ${GElement} >( other: OtherSequence${"," if preds else ""} % if preds: @noescape isOrderedBefore: (${GElement}, ${GElement}) -> Bool % end ) -> Bool { var g1 = self.generate() var g2 = other.generate() while true { if let e1 = g1.next() { if let e2 = g2.next() { if ${"isOrderedBefore(e1, e2)" if preds else "e1 < e2"} { return true } if ${"isOrderedBefore(e2, e1)" if preds else "e2 < e1"} { return false } continue // equivalent } return false } return g2.next() != nil } } } % end //===----------------------------------------------------------------------===// // contains() //===----------------------------------------------------------------------===// extension SequenceType where Self.Generator.Element : Equatable { /// Return `true` iff `x` is in `self`. final public func _prext_contains(element: ${GElement}) -> Bool { if let result = _customContainsEquatableElement(element) { return result } for e in self { if e == element { return true } } return false } } extension SequenceType { /// Return `true` iff an element in `self` satisfies `predicate`. final public func _prext_contains( @noescape predicate: (${GElement}) -> Bool ) -> Bool { for e in self { if predicate(e) { return true } } return false } } //===----------------------------------------------------------------------===// // reduce() //===----------------------------------------------------------------------===// extension SequenceType { /// Return the result of repeatedly calling `combine` with an /// accumulated value initialized to `initial` and each element of /// `self`, in turn, i.e. return /// `combine(combine(...combine(combine(initial, self[0]), /// self[1]),...self[count-2]), self[count-1])`. final public func _prext_reduce( initial: T, @noescape combine: (T, ${GElement}) -> T ) -> T { var result = initial for element in self { result = combine(result, element) } return result } } //===----------------------------------------------------------------------===// // reverse() //===----------------------------------------------------------------------===// extension SequenceType { /// Return an `Array` containing the elements of `self` in reverse /// order. final public func _prext_reverse() -> [${GElement}] { // FIXME(performance): optimize to 1 pass? But Array(self) can be // optimized to a memcpy() sometimes. Those cases are usually collections, // though. var result = Array(self) let count = result.count for i in 0.. BidirectionalReverseView { return BidirectionalReverseView(self) } } extension CollectionType where Self.Index : RandomAccessIndexType { /// Return a lazy `CollectionType` containing the elements of `self` /// in reverse order. final public func _prext_reverse() -> RandomAccessReverseView { return RandomAccessReverseView(self) } } //===----------------------------------------------------------------------===// // filter() //===----------------------------------------------------------------------===// // We would like to make filter() a protocol requirement, and dynamically // dispatched, but Swift generics don't allow us to express this. // rdar://20477576 extension SequenceType { /// Return an `Array` containing the elements of `self`, /// in order, that satisfy the predicate `includeElement`. final public func _prext_filter( @noescape includeElement: (${GElement}) -> Bool ) -> [${GElement}] { // Cast away @noescape. typealias IncludeElement = (${GElement}) -> Bool let escapableIncludeElement = unsafeBitCast(includeElement, IncludeElement.self) return Array<${GElement}>(lazy(self).filter(escapableIncludeElement)) } } //===----------------------------------------------------------------------===// // map() //===----------------------------------------------------------------------===// extension SequenceType { /// Return an `Array` containing the results of mapping `transform` /// over `self`. final public func _prext_map( @noescape transform: (${GElement}) -> T ) -> [T] { // Cast away @noescape. typealias Transform = (${GElement}) -> T let escapableTransform = unsafeBitCast(transform, Transform.self) return Array(lazy(self).map(escapableTransform)) } } //===----------------------------------------------------------------------===// // flatMap() //===----------------------------------------------------------------------===// extension SequenceType { /// Return an `Array` containing concatenated results of mapping `transform` /// over `self`. final public func _prext_flatMap( @noescape transform: (${GElement}) -> S ) -> [S.${GElement}] { var result: [S.${GElement}] = [] for element in self { result.extend(transform(element)) } return result } } extension SequenceType { /// Return an `Array` containing the non-nil results of mapping `transform` /// over `self`. final public func _prext_flatMap( @noescape transform: (${GElement}) -> T? ) -> [T] { var result: [T] = [] for element in self { if let newElement = transform(element) { result.append(newElement) } } return result } }