多多色-多人伦交性欧美在线观看-多人伦精品一区二区三区视频-多色视频-免费黄色视屏网站-免费黄色在线

中國最全IT社區平臺 聯系我們 | 收藏本站
阿里云優惠2

swift教程

Swift函數式編程 惰性計算

閱讀 (3637)

Swift函數式編程-惰性計算

Swift支持函數式編程,這一篇介紹Swift的惰性計算。

惰性計算

惰性計算是函數式編程語言的一個特性。在使用惰性計算時,表達式不在它被綁定到變量之后就立即求值,而是在該值被取用的時候求值。惰性計算有如下優點:

  • 首先,你可以用它們來創建無限序列這樣一種數據類型。因為直到需要時才會計算值,這樣就可以使用惰性集合模擬無限序列。

  • 第二,減少了存儲空間。因為在真正需要時才會發生計算。所以,節約了不必要的存儲空間。

  • 第三,減少計算量,產生更高效的代碼。因為在真正需要時才會發生計算。例如,尋找數組中第一個符合某個條件的值。

在純函數式編程語言,如Haskell中是默認進行惰性求值的。所以,Haskell被稱為惰性語言。而與之相對的大多數編程語言如Java,C++ 的求值都是嚴格的,或者說是及早求值。Swift默認是嚴格求值的,也就是每一個表達式都需要求值,而不論這個表達式在實際中是否確實需要求值。但是,Swift作為支持多種范型的編程語言,也同時提供語法來支持惰性求值。

內建 lazy 函數

Swift中,如果需要惰性計算,就要顯式地將一個序列轉化為惰性序列。轉化方法是使用Swift內建的lazy函數。它有四個重載實現。編譯器會為你選擇最正確的實現。

如果傳入lazy的是Sequence(實現了SequenceType協議的類或者結構體),返回的會是LazySequence;如果傳入一個Collection(實現了CollectionType協議的的類或者結構體),返回的會是LazyForwardCollectionLazyBidirectionalCollection, 或者LazyRandomAccessCollection。 下面是lazy函數的四個函數重載函數的函數原型:

func lazy<S: SequenceType>(s: S) -> LazySequence<S>
func lazy<S: CollectionType where S.Index: ForwardIndexType>(s: S) -> LazyForwardCollection<S>
func lazy<S: CollectionType where S.Index: BidirectionalIndexType>(s: S) -> LazyBidirectionalCollection<S>
func lazy<S: CollectionType where S.Index: RandomAccessIndexType>(s: S) -> LazyRandomAccessCollection<S>

如果,傳入一個Array,返回的將是LazyRandomAccessCollection類型。LazyRandomAccessCollection是惰性集合。下面展示了一個將Array變為惰性序列的例子:

let r = 1...3
let seq = lazy(r).map {
    (i: Int) -> Int in
    println("mapping \(i)")
    return i * 2
}

for i in seq {
    println(i)
}

將獲得如下結果:

mapping 1
2
mapping 2
4
mapping 3
6

這顯示了seq是一個惰性序列。它的值只有在需要時才會真正發生計算。

Generator

Swift中,Generator是任何實現了GeneratorType協議的類或者結構體。Generator可以理解為一個序列生成器。GeneratorType協議要求定義一個名為Element的別名,并實現一個next方法。

GeneratorType協議實現如下:

protocol GeneratorType {
    typealias Element
    mutating func next() -> Element?
}

語句typealias Element要求實現這個協議的類必須定義一個名為Element的別名,這樣一定程度上實現了泛型協議。協議同時要求實現next函數,其返回值是別名中定義的Element類型,next函數代表生成器要生成的下一個元素。

下面代碼實現了一個菲波那契數列生成器:

class FibonacciGenerator : GeneratorType {

    var current = 0, nextValue = 1  

    typealias Element = Int

    func next() -> Element? {
        let ret = current
        current = nextValue
        nextValue = nextValue + ret
        return ret
    }
}

下面代碼打印出10個菲波那契數列,以顯示如何使用生成器:

var n = 10
var generator = FibonacciGenerator()
while n-- > 0 {
    println(generator.next()!)
}

Generator是Sequence和Collection的基礎。

Sequence

Sequence是任何實現了SequenceType協議的類或者結構體。Sequence可以理解為一個序列。SequenceType協議要求定義一個名為Generator,類型為GeneratorType的別名,并要求實現一個返回生成器Generator的函數。

SequenceType協議如下:

protocol SequenceType : _Sequence_Type {
    typealias Generator : GeneratorType
    func generate() -> Generator
}

類似于GeneratorType協議,typealias Generator : GeneratorType要求實現這個協議的類必須定義一個名為Generator類型為GeneratorType的別名。協議同時要求實現一個名為generate的函數,其返回值為別名Generator定義的類型,這個類型應該實現了上文提到的GeneratorType協議。也就是說Sequence其實是包含一個生成Generator的函數的類。

下面代碼使用上文中提到的菲波那契數列生成器,實現了一個菲波那契數列:

class FibonacciSequence: SequenceType
{
    typealias GeneratorType = FibonacciGenerator

    func generate() -> FibonacciGenerator {
        return FibonacciGenerator()
    }
}

下面代碼打印了10個菲波那契數列,以顯示如何使用該序列:

let fib = FibonacciSequence().generate()
for _ in 1..<10 {
    println(fib.next()!)
}

符合SequenceType的序列有可能成為惰性序列。成為惰性序列的方法是對其顯示的調用lazy函數:

let r = lazy(stride(from: 1, to: 8, by: 2))

函數stride返回一個結構體StrideTo,這個結構體是Sequence。所以,lazy函數返回一個lazySequence對象。

Collection

Collection是實現了CollectionType協議的協議的類或者結構體。CollectionType協議繼承了SequenceType協議。所以,Collection也都實現了SequenceType,它同時也是Sequence。

CollectionType協議如下:

protocol _CollectionType : _SequenceType {
    typealias Index : ForwardIndexType
    var startIndex: Index { get }
    var endIndex: Index { get }
    typealias _Element
    subscript (_i: Index) -> _Element { get }
}

protocol CollectionType : _CollectionType, SequenceType {
    subscript (position: Self.Index) -> Self.Generator.Element { get }
}

所以,CollectionType協議首先實現了SequenceType協議,并要求實現一個subscript方法以獲取序列中每個位置的元素值。

Swift中,大量內置類如Dictionary,Array,Range,String都實現了CollectionType協議。所以,Swift大部分容器類都可以變為惰性序列。

// a will be a LazyRandomAccessCollection
// since arrays are random access
let a = lazy([1,2,3,4])

// s will be a LazyBidirectionalCollection
let s = lazy("hello")

總結

Swift里的集合數據結構默認是嚴格求值的。但是,Swift也提供了惰性語法,在需要惰性時,你需要顯式聲明。這為開發者在Swift中使用惰性提供了條件。

原文出處:http://lincode.github.io/Swift-Lazy
作者:LinGuo

關閉
程序員人生
主站蜘蛛池模板: 亚1州区2区三区4区产品 | 欧美性精品 | 免费www| 国产精品国产三级国产 | 亚洲色图1 | 国产精品高清一区二区三区 | 欧美一级高清在线观看 | 日韩爱爱 | 亚洲人成网亚洲欧洲无码 | 久久精品国产在热久久2019 | 国产91精品高跟丝袜在线 | 亚洲色图第三页 | 国产精品原创永久在线观看 | 在线www| 在线h网站 | 精品欧美视频 | 国内自拍视频在线看免费观看 | 成人资源在线观看 | 91中文字幕yellow字幕网 | 国产一区二区三区欧美精品 | 波多野结衣在线观看3人 | 亚洲国产成人久久99精品 | 黑人巨大xxxx | 欧美一区二区三区视频在线 | 国产大学生露脸激情 | 一级毛片毛片毛片毛毛片 | 亚洲a级毛片| 欧美精品一区二区三区免费播放 | 国产欧美综合一区二区 | 精品一区二区三 | 亚洲图片偷拍自拍 | 91精品国产人成网站 | 性加拿大高清xxxxx | 日本高清www无色夜在 | 亚洲精品一二三区-久久 | ww视频在线观看 | 精品一区二区三区无卡乱码 | 久久久免费精品视频 | 亚洲精品综合一区二区三区在线 | 国产成人一区二区三区在线视频 | 亚洲国产精品免费在线观看 |