Swift 押さえておきたい構文 「Closure」で”できる事”①
筆者がいろんな言語を使用してきて、他の言語と異なる気になると感じたSwiftで押さえておきたい構文を「なにが出来るの?」といった視点で紹介していきます。
今回はClosure(クロージャ)について公式サイトの説明を使用しながら解りやすく解説していきます。
クロージャーの使用例
ケース1. 共通処理に詳細条件処理をクロージャとして渡す
・ソート処理に、ソート条件を定義したクロージャを渡しソートする。
ケース2. 非同期関数に終了処理を定義したクロージャを渡し非同期処理終了時に処理する
などに用います。
クロージャ(Closure)とは?
クロージャ(Closure)は、コード内で渡して使用できる自己完結型の処理ブロックです。
SwiftのクロージャはC及びObjective-Cのブロックや、他のプログラミング言語のラムダ式に似ていて、定義されるコンテキストから、定数、変数への参照をキャプチャして保存できます。
クロージャでできる事
・処理ブロックを作成できる
クロージャ式の構文(Closure Expression Syntax)
一般的なクロージャー式の構文
{ (引数) -> 戻り値型 in
statements
}
波{}で囲んだ処理ブロックになります。
一般的な関数との違いは、
・関数名なし
・通常の関数は戻り値型の後に波{}で処理ブロックを囲むがクロージャ、
引数の()を含むクロージャー全体を波{}で囲む
・戻り値型の後に「in」を記述し処理ブロック記述を開始する
以上のことから、名前なし関数をイメージすると理解しやすくなるかとおもいます。
同じ処理内容を関数と、一般的なクロージャで記述した場合 以下の形になります。
関数の記述
func method( parameter: Int) -> Int {
return parameter * 10
}
クロージャーの記述
{ (parameter: Int) -> Int in
return parameter * 10
}
クロージャの種類
グローバル関数とネストされた関数はクロージャの特殊なケースで、
クロージャーは次の3つ形式のいずれかになります。
- グローバル関数
名前を持ち、値をキャプチャしないクロージャー - ネストされた関数
名前を持ち、囲んでいる関数から値をキャプチャできるクロージャ - クロージャー式
周囲のコンテキストから値をキャプチャできる軽量の構文で記述された名前のないクロージャー
最適化されたSwiftのクロージャ
- コンテキストからのパラメーターと戻り値の型推論
- 単一式クロージャーからの暗黙の戻り
- 引数名の省略形
- トレーリングクロージャの構文
次のようなコードで順番に見ていきましょう
let fruit = ["Orange","Banana","Melo"n,"Grapes","Pear","Peaches"]
sortFruit = fruit.sorted(by: { (s1: String, s2: String) -> Bool in return s1 > s2})
コンテキストからのパラメーターと戻り値の型推論
sortクロージャは引数としてメソッドに渡されるため、Swiftはそのパラメーターの型とそれが返す値の型を推測できます。
sorted(by:)メソッドは文字列の配列に対して呼び出されているため、その引数は(String,String)→Bool型でなければなりません。すべての型を推測できるため戻り矢印(->) とパラメーターの名前を囲むかっこも省略できます。
sortFruit = fruit.sorted(by:{ s1, s2 in return s1 > s2 }
単一式クロージャーからの暗黙の戻り
単一式クロージャは、返り値が明確である場合、宣言からreturnキーワードを省略する事が可能。
sortFruit = fruit.sorted(by:{s1,S2 in s1 > s2 })
省略形の引数名
インラインクロージャに省略型の引数名を自動的に提供します。$0、$1、$2などの名前でクロージャの引数の値を参照可能です。クロージャ式は本体全体で構成されているためinキーワードも省略できます。
sortFruit = fruit.sorted(by: { $0 > $1 } )
さらに、String型の2つのパラメータを持ちBool型のの値を返すメソッドはsorted(by:)メソッドで必要なメソッドタイプと正確に一致します。したがって単に大なり演算子を渡すだけでSwiftはその文字列固有の実装を使用したと推測します。
このことを知らずにソースコードだけみると何がなんだかわかりませんね。
sortFruit = fruit.sorted(by:>)
続きは以下にて紹介していますのでよかったら参照してみてください。