15
12

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

[Swift4] 遅延評価のすゝめ 〜 LazySequence/LazyCollection

Last updated at Posted at 2017-10-15

mapなどによる無駄な処理

[Int]である配列の要素に1を加えて2を掛け最初の要素を取り出してみます。
処理の流れを見るために出力を付け加えています。


func add(_ i: Int) -> (Int) -> Int {
    return {
        print("<<", $0)
        return $0 + i
    }
}
func multiply(_ i: Int) -> (Int) -> Int {
    return {
        print($0 * i, ">>")
        return $0 * i
    }
}

let re = Array(0..<5).map(add(1)).map(multiply(2)).first

これを実行すると

<< 0
<< 1
<< 2
<< 3
<< 4
2 >>
4 >>
6 >>
8 >>
10 >>

と出力され、reには2が代入されます。
最初のmapで全ての要素に1を加え、続くmapで全ての要素に2をかけ、その後、最初の要素を取り出しています。

必要な値は

let re = (0 + 1) * 2

だけで計算可能であるのに、無意味な計算が多数行われます。
これを解決するのがLazySequence/LazyCollectionとそのサブタイプです。

遅延評価

先ほどのプログラムにちょっと追加をします。

let re = Array(0..<5).lazy.map(add(1)).map(multiply(2)).first

lazyを追加しただけです。
これを実行すると

<< 0
2 >>

と出力され、reには2が代入されます。

最初の要素、つまり

let re = (0 + 1) * 2

だけが計算されているのがわかります。

これはつまり、mapに渡された関数の実行はその場ではされず、実際に値が必要になった時必要な要素のみに、この場合はfirstが呼ばれた時に必要である最初の要素に対してのみ関数が実行されているのです。

このように、実際の値が必要になるまで、mapなどに与えられる関数の実行を遅延させるのが遅延評価であり、Swiftにおいてその役割を担っているのがLazySequence/LazyCollectionとそのサブタイプです。

いつ実行されるの?

LazySequence/LazyCollectionとそのサブタイプ自身はあまり覚える必要はありませんが、それらに対して、何をした時何が起こるのかというのは重要です。

遅延評価させるつもりで書いたものが、遅延評価になっていなかったというのが一番問題なのです。

ということで、未完成ですが、僕が現在調べた結果を記しておきます。
ハイライトされて読みやすくなるようにメソッドにはfuncをプロパティにはvarをつけています。

実行されない

func map(_:)
func flatMap(_:)

func filter(_:)

func enumerated()

func reversed()

func prefix(_:)
func prefix(through:)
func prefix(upTo:)
func prefix(while:)

func suffix(_:)
func suffix(from:)

func dropFirst()
func dropFirst(_:)
func dropLast()
func dropLast(_:)

func joined()

該当箇所のみ実行される

var first

var last

条件が満たされるまで/満たされている間実行される


func first(where:)

func contains()

func index(where:)

var isEmpty

全て実行される

// 通常の配列などに変換する
let array = Array(lazySequence)

func reduce(_:,_:)

func sorted()
func sorted(by:)

func joined(separator:)

未完成

未完成なので、ちょっとつづ追加していきたい。

15
12
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
15
12

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?