Closureの即時実行を使ったスコープの切り分け

Swiftのletはimmutableな変数宣言で、一度値を入れたらその後に変更することができない。

let hoge = "hoge"
hoge = "fuga" // コンパイルエラー

これは変数宣言のときに値を入れないといけない、という制限ではなく、その変数が使われるまでに値が入っていれば問題ない。 ただし、その場合は型の宣言を省略できない。

let hoge: String
hoge = "hoge" // OK

「その変数が使われるまでに値が入っていれば問題ない。」というのは例えばif文やswitch文を使っても大丈夫

let hoge: String
if arc4random() % 2 == 0 {
    str = "even"
} else {
    str = "odd"
}
debugPrint(str) // "even" もしくは "odd"が出力される

たまに処理が複雑で使い捨て変数を割り当てないといけないことがある。

let array = Array(1...10)
var sum = 0
array.forEach({ sum += $0 })
let average = sum / array.count

このときsum変数は一時的な変数で、averageを求めたら必要なくなる。このexampleではそんなことないんだけど、使い捨ての変数名を考えるが面倒で、手が止まってしまうことがしばしばあり、違うスコープを切りたい時に有効なのがクロージャだ。

let array = Array(1...10)
let average: Int = {
    var sum = 0
    array.forEach({ sum += $0 })
    return sum / array.count
}()

クロージャ内部は別のスコープなので、使い捨ての変数は本当に使いたい部分でだけ有効になる。 まぁそもそもこのexampleではreduceを使えばいい話なんだけど…

let average = array.reduce(0) { sum, i in sum + i } / array.count

Viewに関するコードを書いていると使い捨ての変数を定義したくなることがあるので、そういうときに使うと便利。