Created
October 18, 2019 02:52
-
-
Save omochi/e9217820fb32953a23179fa4aa36ee45 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import Foundation | |
protocol Iterator { | |
associatedtype Element | |
associatedtype Failure: Error | |
func _next() throws -> Element? | |
} | |
extension Iterator { | |
func next() throws -> Element? { try _next() } | |
} | |
// 例外飛ばない版 | |
// 本体の定義が`_next`なのは、もし`next`だとここで自己再起しちゃうから。。 | |
extension Iterator where Failure == Never { | |
func next() -> Element? { try! _next() } | |
} | |
struct AnyIterator<Element, Failure: Error>: Iterator { | |
func _next() throws -> Element? { fatalError("実装省略") } | |
} | |
// ジェネリックなユーザー | |
// これを書く事自体はそんなに大変ではないと思う。 | |
// throwsをつけるのと、tryをつけるだけ。 | |
func dropA<X: Iterator>(iterator: X, n: Int) throws { | |
for _ in 0..<n { | |
_ = try iterator.next() | |
} | |
} | |
// ジェネリックなユーザーしか無い時のそのユーザー | |
func appA(a: AnyIterator<Int, Never>) { | |
// dropが例外を投げる版しか無いのでこうなっちゃう・・・ | |
try! dropA(iterator: a, n: 1) | |
} | |
// もうひと頑張りしておいた場合 | |
func _dropB<X: Iterator>(iterator: X, n: Int) throws { | |
for _ in 0..<n { | |
_ = try iterator.next() | |
} | |
} | |
func dropB<X: Iterator>(iterator: X, n: Int) throws { | |
try _dropB(iterator: iterator, n: n) | |
} | |
func dropB<X: Iterator>(iterator: X, n: Int) where X.Failure == Never { | |
try! _dropB(iterator: iterator, n: n) | |
} | |
func appB(a: AnyIterator<Int, Never>) { | |
// Neverだから例外なし版が呼べる | |
dropB(iterator: a, n: 1) | |
} | |
/** | |
総評 | |
dropBみたいなボイラープレートを毎回2種類書けば実現できるが面倒なので実際は多分誰もやらない。 | |
引数のIteratorの数に応じて2^nでバリエーションが出てしまうので、 | |
3引数とかになるだけで8通りになって無理。 | |
*/ | |
// こういう仕組みが必要なのかもしれない | |
// iterator.nextの呼び出しから例外が飛ばないことがXの型からわかるとき、 | |
// dropCからも例外を飛ばないということを宣言したい | |
// rethrows句自体はすでにあるけど、クロージャを渡した場合に限られた機能なので、 | |
// これを拡張する。 | |
func dropC<X: Iterator>(iterator: X, n: Int) rethrows(from iterator.next) { | |
for _ in 0..<n { | |
_ = try iterator.next() | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Typed throwsがあればいいのか。