swiftを久々に触ったら、クロージャの文法を完全に忘れていたので、メモしておく。
Closure Expression Syntax
クロージャはこの形をしている。
{ (parameters) -> return type in statements }
例えば、このように使う。
let names = ["Chris", "Alex", "Ewa", "Barry", "Daniella"] reversed = names.sort( { (s1: String, s2: String) -> Bool in return s1 > s2 } )
Inferring Type From Context
sortメソッドの引数に渡せるクロージャの型は決まっており、コンパイラが引数や戻り値を推測するため、
クロージャでは引数や戻り値の型を省略できる。
「戻り値の型を省略した場合、引数を囲むカッコ()は省略できる。」
ので、このように書ける。
reversed = names.sort( { s1, s2 in return s1 > s2 } )
戻り値が一つの場合はreturnも省略できる。
reversed = names.sort( { s1, s2 in s1 > s2 } )
Shorthand Argument Names
クロージャでは簡易引数表現が使える。
$0は1番目の引数、$1は2番目の引数を表す。
reversed = names.sort( { $0 > $1 } )
Trailing Closures
関数の最後の引数としてクロージャを渡す場合、関数に渡すクロージャ文をカッコの外に記述することができる。
次のように書ける。
reversed = names.sort() { $0 > $1 }
クロージャをカッコ外に記述した結果、それ以外の引数がない時は、残ったカッコ()は省略することができる。
reversed = names.sort { $0 > $1 }
Capturing Values
値のキャプチャ
以下を考える。
func makeIncrementer(forIncrement amount: Int) -> () -> Int { var runningTotal = 0 func incrementer() -> Int { runningTotal += amount return runningTotal } return incremented } let incrementer_even = makeIncrementer(forIncrement: 2) let val1 = incrementer_even() // 2 let val2 = incrementer_even() // 4 let val3 = incrementer_even() // 6
makeIncrementerは関数を戻り値として返す関数である。
値のキャプチャという分かりづらい表現で説明されているが、C++でいうところのrunningTotalという状態変数を持つ関数オブジェクト(ファンクタ)と同じ機能だと考えた方が分かりやすい。
runningTotalという状態変数はincremented_evenのインスタンスが解放されたタイミングで解放される。