美文网首页
swift-Sequence

swift-Sequence

作者: Mjs | 来源:发表于2021-01-13 15:46 被阅读0次

Iterators

在我们研究Sequence之前,我们先从我们日常比较常见的一段代码入手:

let numbers = [2,4,6,8]

for num in numbers{
    print(num)
}

系统的底层是如何实现for...in,接下来我们通过SIL观察一下:

  // function_ref Collection<>.makeIterator()   这里创建一个makeIterator
  %34 = function_ref @(extension in Swift):Swift.Collection< where A.Iterator == Swift.IndexingIterator<A>>.makeIterator() -> Swift.IndexingIterator<A> : $@convention(method) <τ_0_0 where τ_0_0 : Collection, τ_0_0.Iterator == IndexingIterator<τ_0_0>> (@in τ_0_0) -> @out IndexingIterator<τ_0_0> // user: %35
  %35 = apply %34<Array<Int>>(%29, %32) : $@convention(method) <τ_0_0 where τ_0_0 : Collection, τ_0_0.Iterator == IndexingIterator<τ_0_0>> (@in τ_0_0) -> @out IndexingIterator<τ_0_0>
  dealloc_stack %32 : $*Array<Int>                // id: %36
  br bb1                                          // id: %37

bb1:                                              // Preds: bb3 bb0
  %38 = alloc_stack $Optional<Int>                // users: %43, %44, %41
  %39 = begin_access [modify] [static] %29 : $*IndexingIterator<Array<Int>> // users: %42, %41
  // function_ref IndexingIterator.next()
  %40 = function_ref @Swift.IndexingIterator.next() -> A.Element? : $@convention(method) <τ_0_0 where τ_0_0 : Collection> (@inout IndexingIterator<τ_0_0>) -> @out Optional<τ_0_0.Element> // user: %41
  %41 = apply %40<Array<Int>>(%38, %39) : $@convention(method) <τ_0_0 where τ_0_0 : Collection> (@inout IndexingIterator<τ_0_0>) -> @out Optional<τ_0_0.Element>
  end_access %39 : $*IndexingIterator<Array<Int>> // id: %42
  %43 = load %38 : $*Optional<Int>                // user: %45
  dealloc_stack %38 : $*Optional<Int>             // id: %44
  switch_enum %43 : $Optional<Int>, case #Optional.some!enumelt.1: bb3, case #Optional.none!enumelt: bb2 // id: %45

可以看到,这里调用了Collection协议中的makeIterator()方法,创建了一个indexingIterator,接着调用indexingIterator.next()方法来不断拿到元素,也就意味着我们平常写的for...in是不存在的,for...in是一个语法糖。

我们来找到Sequence.swift这个文件,IteartorProtocol是一个一次提供一个序列值的类型,它和Sequence协议是息息相关的,Sequence每次通过创建迭代器来访问序列中的元素。

所以我们每次在使用for..in的时候,其实都是使用这个集合的迭代器来遍历当前集合或者序列当中的元素。

我们来看一下IteratorProtocol的定义:

public protocol IteratorProtocol {
  /// The type of element traversed by the iterator.
//关联类型,实现该协议时,需要执行Element的类型
  associatedtype Element

  mutating func next() -> Element?
}

当前协议有一个关联类型Element,其实有一个mutating的方法nextnext方法返回一个element

接下来就是Sequence协议的定义


public protocol Sequence {
  /// A type representing the sequence's elements.
  associatedtype Element

  /// A type that provides the sequence's iteration interface and
  /// encapsulates its iteration state.
  associatedtype Iterator: IteratorProtocol where Iterator.Element == Element

  /// A type that represents a subsequence of some of the sequence's elements.
  // associatedtype SubSequence: Sequence = AnySequence<Element>
  //   where Element == SubSequence.Element,
  //         SubSequence.SubSequence == SubSequence
  // typealias SubSequence = AnySequence<Element>

  /// Returns an iterator over the elements of this sequence.
  __consuming func makeIterator() -> Iterator
......
}

对于Sequence协议来说,表达的是既可以是一个有限的集合,也可以是一个无限的集合,而它只需要提供集合中的元素,和如何访问这些元素的接口即可。

我们来自定义的试一下:假设我们要用一个结构体来模拟一个集合,对于一个给定的初始值,那么当前集合中包含从 0...count的整形集合。

struct LGSequence:Sequence {
    typealias Element = Int
    
    var arrayCount: Int
    
    func makeIterator() -> LGIterator {
        return LGIterator(self)
    }
}

struct LGIterator: IteratorProtocol {
    typealias Element = Int
    
    let seq: LGSequence
    
    init(_ sequence : LGSequence) {
        self.seq = sequence
    }

    var count = 0

    mutating func next() -> Int? {
        
        guard count < self.seq.arrayCount else {
            return nil
        }
        
        count += 1
        
        return count
        
    }
}

let seq = LGSequence.init(arrayCount: 10)

for element in seq{
    print(element)
}
·······························
1
2
3
4
5
6
7
8
9
10

相关文章

  • swift-Sequence

    Iterators 在我们研究Sequence之前,我们先从我们日常比较常见的一段代码入手: 系统的底层是如何实现...

  • swift-sequence 序列

    swift下有许多的高阶函数如:map 重对应的一个类型映射到另一个类型的整合函数 这样就可以实现对自定义对象

网友评论

      本文标题:swift-Sequence

      本文链接:https://www.haomeiwen.com/subject/kqesaktx.html