LazySequenceProtocol
聲明
protocol LazySequenceProtocol : Sequence
概述
惰性序列可用於避免不必要的存儲分配和計算,因為它們使用底層序列進行存儲並按需計算其元素。例如,此代碼示例中的 doubled
是一個包含值 2
、 4
和 6
的序列。
let doubled = [1, 2, 3].lazy.map { $0 * 2 }
每次訪問惰性序列doubled
的元素時,閉包都會訪問並轉換底層數組的元素。
采用閉包參數的序列操作,例如 map(_:)
和 filter(_:)
,通常是即刻的:它們立即使用閉包並返回一個新數組。當您使用lazy
屬性時,您授予標準庫顯式權限以將閉包和序列存儲在結果中,並將計算推遲到需要時。
添加新的惰性操作
要添加新的惰性序列操作,請使用返回惰性包裝器的方法擴展此協議,該包裝器本身符合 LazySequenceProtocol
。例如,一個 Eager scan(_:_:)
方法定義如下:
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
}
}
您可以構建一個序列類型,以延遲計算掃描結果中的元素:
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)
}
}
最後,你可以給所有惰性序列一個惰性scan(_:_:)
方法:
extension LazySequenceProtocol {
func scan<Result>(
_ initial: Result,
_ nextPartialResult: @escaping (Result, Element) -> Result
) -> LazyScanSequence<Self, Result> {
return LazyScanSequence(
initial: initial, base: self, nextPartialResult: nextPartialResult)
}
}
使用這種類型和擴展方法,您可以在任何序列上調用.lazy.scan(_:_:)
來創建延遲計算掃描。生成的 LazyScanSequence
本身也是惰性的,因此進一步的序列操作也會延遲計算。
延遲實現操作的顯式權限僅適用於靜態已知序列符合 LazySequenceProtocol
的上下文。在以下示例中,由於擴展僅適用於 Sequence
,因此 side-effects (例如 result
的累積)永遠不會意外刪除或延遲:
extension Sequence where Element == Int {
func sum() -> Int {
var result = 0
_ = self.map { result += $0 }
return result
}
}
但是,實際上不要為此使用map
,因為它會創建並丟棄結果數組。相反,使用reduce
進行求和操作,或使用forEach
或for
- in
循環進行有副作用的操作。
可用版本
相關用法
- Swift LazySequence split(maxSplits:omittingEmptySubsequences:whereSeparator:)用法及代碼示例
- Swift LazySequence suffix(from:)用法及代碼示例
- Swift LazySequence allSatisfy(_:)用法及代碼示例
- Swift LazySequence map(_:)用法及代碼示例
- Swift LazySequence last用法及代碼示例
- Swift LazySequence elementsEqual(_:)用法及代碼示例
- Swift LazySequence shuffled()用法及代碼示例
- Swift LazySequence enumerated()用法及代碼示例
- Swift LazySequence dropLast(_:)用法及代碼示例
- Swift LazySequence sorted()用法及代碼示例
- Swift LazySequence firstIndex(where:)用法及代碼示例
- Swift LazySequence lastIndex(where:)用法及代碼示例
- Swift LazySequence last(where:)用法及代碼示例
- Swift LazySequence index(_:offsetBy:limitedBy:)用法及代碼示例
- Swift LazySequence firstIndex(of:)用法及代碼示例
- Swift LazySequence randomElement()用法及代碼示例
- Swift LazySequence first(where:)用法及代碼示例
- Swift LazySequence contains(where:)用法及代碼示例
- Swift LazySequence index(_:offsetBy:)用法及代碼示例
- Swift LazySequence randomElement(using:)用法及代碼示例
- Swift LazySequence compactMap(_:)用法及代碼示例
- Swift LazySequence first用法及代碼示例
- Swift LazySequence subscript(_:)用法及代碼示例
- Swift LazySequence max()用法及代碼示例
- Swift LazySequence suffix(_:)用法及代碼示例
注:本文由純淨天空篩選整理自apple.com大神的英文原創作品 LazySequenceProtocol。非經特殊聲明,原始代碼版權歸原作者所有,本譯文未經允許或授權,請勿轉載或複製。