標籤:test collect get 需要 儲存 == htm 編譯 fun
Swift 之惰性求值
在 Haskell 中的函數有一個特性
函數的返回可能是一個塊(一個被延遲計算的運算式)
從而引出一個概念 惰性求值
isOdd n = mod n 2 == 1
下面有段 分析
在使用嚴格求值的語言裡,函數的參數總是在應用函數之前被求值。以 isOdd 為例子:子運算式 (1 + 2)會首先被求值,得出結果 3 。接著,將 3 綁定到變數 n ,應用到函數 isOdd 。最後, mod 3 2 返回 1 ,而 1 == 1 返回 True 。Haskell 使用了另外一種求值方式 —— 非嚴格求值。在這種情況下,求值 isOdd (1 + 2) 並不會即刻使得子運算式 1 + 2 被求值為 3 ,相反,編譯器做出了一個“承諾”,說,“當真正有需要的時候,我有辦法計算出 isOdd (1 + 2) 的值”。
惰性求值的優點
簡單理解惰性求值: 在使用惰性計算時,運算式不在它被綁定到變數之後就立即求值,而是在該值被取用的時候求值。
- 可以建立無限序列資料類型, 比如無窮大,由於位元組的限制,很多語言並不能描述出無窮大
- 減少儲存空間, 在要求值的時候才會發生計算。 這個跟
lazy 屬性一樣的作用
- 減少計算量, 例如,尋找數組中合格某個值
swift 預設嚴格求值, 也提供了相關的惰性求值的機制
let array = [1,2,4,5,3,7]let selement = array.map({$0 * 2})[3]let element = array.lazy.map({$0 * 2 })[3]print("\(selement) -- \(element)")
上面代碼中, 計算出 selement 花了 7 次, 計算 element 花了 2 次
- 對於
7:將 array 每個元素分別取出 * 2,然後在這些資料中取出第4個元素, 6+1=7
- 對於
2:因為是惰性求值,會先從 array 取出第4個元素, 然後 * 2 , 1+1 = 2
lazy 到底為何物?
extension Array { public var lazy: LazyRandomAccessCollection<Array<Element>> { get }}
LazyRandomAccessCollection Conforms To
LazyCollectionProtocol
LazyCollectionProtocol Conforms To
LazySequenceProtocol
構建無窮大序列 (swift4)
enum Stream<T> { case empty case cons(()->T, ()-> Stream<T>)}extension Stream { var empty: Stream<T> { return .empty } var tail: Stream<T> { switch self { case .empty: return .empty case let .cons(_, tail): return tail() } } var toArray: [T] { switch self { case .empty: return [] case let .cons(h, t): return [h()] + t().toArray } } func take(n: Int) -> Stream<T> { if n == 0 { return empty } else { switch self { case .empty: return .empty case let .cons(h, t): return Stream.cons(h, {t().take(n: n-1)}) } } }}func onses() -> Stream<Int> { return Stream<Int>.cons({1}, {onses()})}print(onses().take(n: 5).toArray)
當然更多部落格請移步到 這裡
參考
- Swift 函數式編程-惰性計算
- Swift函數式編程(二):惰性求值與無窮資料流
Swift 之惰性求值