Skip to content

Instantly share code, notes, and snippets.

@pofat
Last active February 17, 2020 08:58
Show Gist options
  • Save pofat/8626b181459ef8846fb99d903617dc0a to your computer and use it in GitHub Desktop.
Save pofat/8626b181459ef8846fb99d903617dc0a to your computer and use it in GitHub Desktop.
如何用 generic struct 消除 PAT 的問題
// 利用 init with closure 來自動代入 `Element` 真實的型別,而不是直接用 <某型別> 的方式來指定
// 先宣告一個 generic struct
struct MyAnyIterator<Element> {
// 內部使用的 Box ,裡面就是把 closure 存起來,本身也滿足 IteratorProtocol
private class AnyIteratorBox<Element>: IteratorProtocol {
typealias Base = () -> Element?
private var _base: Base
init(_ base: @escaping Base) {
self._base = base
}
func next() -> Element? {
return _base()
}
}
// 把 closure 包起來的 box ( 簡單一點也可讓 box 就是個 closure type 直接存 closure)
private let box: AnyIteratorBox<Element>
init(_ body: @escaping () -> Element?) {
self.box = AnyIteratorBox(body)
}
}
// 再讓本身滿足 IteratorProtocol
extension MyAnyIterator: IteratorProtocol {
mutating func next() -> Element? {
return box.next()
}
}
// Fibonacci iterator
var state = (0, 1)
var myIterator = MyAnyIterator { () -> Int in
let upcomingNumber = state.0
state = (state.1, state.0 + state.1)
return upcomingNumber
}
print(myIterator.next()) // 0
print(myIterator.next()) // 1
print(myIterator.next()) // 1
print(myIterator.next()) // 2
print(myIterator.next()) // 3
print(myIterator.next()) // 5
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment