目次
0から学ぶClosure
一般的な関数では変数を引数として変数を戻り値とします.
Closureは関数を引数として関数を戻り値とします.
よく説明されるClosureの認識ですが,{ }を使ったらClosureという認識が強いと思います.
今回はその認識を100%わかるように0からClosureを説明していきたいと思います.
Closureの定義の前に復習
引数があり戻り値もある関数は,以下のように表されます.
func functionName(parameter: parameterType) -> returnType{
//色々処理
return output
}
これらはどんな言語でも共通していることです.
parameterTypeに何かしらのインプットを行いreturnTypeでアウトプットします.
ここでわからない人は,関数の記事を書いたのでそちらを参考にしてください.
関数の3つの定義 ~Learn Swift for Beginners~
Closureの起源
まず,足し算を行う関数を考えてみましょう.
func calc(num1:Int,num2:Int) -> Int {
return num1 + num2
}
calc(num1: 2, num2: 5)
//return 7
引数と戻り値がある関数の定義から計算を行なっています.
これがClosureとどんな関係があるのでしょうか?
calc関数の足し算を掛け算に変えてみましょう
func multiply(num1:Int,num2:Int) -> Int {
return num1 * num2
}
calc(num1: 2, num2: 5)
//return 10
はい.この関数は,形を変えずに処理だけを変えることができています.
ではこれらのcalc関数に足し算か掛け算を指定できるような関数を作れそうな気がしてきました?
これがClosureを含んだ関数の書き方
func calc(n1:Int,n2:Int,operation:(Int,Int)->Int) -> Int {
return operation(n1,n2)
}
新しく計算の引数を付け加えました.
operationには(Int,Int) の引数と戻り値がIntの関数を代入することができます.
そしてcalc関数にoperationを戻り値に設定することができます.
Closureとなりうる関数
func add(n1: Int, n2: Int) -> Int {
return n1 + n2
}
func multiply(n1:Int,n2:Int) -> Int {
return n1 * n2
}
operationにいれる関数これこそがClosureとなりうる関数です.
名前のある関数を使ってのClosure
いきなり無名関数を扱っても分かりにくいので名前のある関数を作成してそれをClosureに代入してみましょう.
func add(num1:Int,num2:Int) -> Int {
return num1 + num2
}
func multiply(num1:Int,num2:Int) -> Int {
return num1 * num2
}
どちらも(Int,Int) の引数と戻り値がIntの関数になっていますよね?
calc(num1:Int, num2:Int, operation:(Int, Int) -> Int)
これらを計算してみると,
calc(n1: 2, n2: 5, operation: add)
//return 7
calc(n1: 2, n2: 5, operation: multiply)
//return 10
引数にadd や multiplyを入れることで関数を実行することができました.
しかし,かなりコードを書きましたね.これはまだ未完成のClosureです.
Closureは無名関数などと言われていますが,今のところ名のある関数しか実行していません.😅今からより簡潔に書く方法の紹介をします。
無名関数を扱ったClosure
では今からClosureの威力を見ていきましょう.
Closureのルールを説明します.
有名の関数を代入しましたが,今から無名の関数に変化させたいと思います.
有名→無名関数に変化させるルール
名のある関数を無名関数に変化させたいと思います.
いくつかルールがあるのでそのルールに沿って変化させたいと思います.
- 関数のfunc addの文字を削除
- { を関数の初めに持ってくる.
- outputの型の右に in を入れる.
この無名関数をcalc関数に入れてみると.
calc(n1: 2, n2: 5, operation: {(num1:Int,num2:Int) -> Int in
return num1 + num2
})
これでClosureを使った式になりました.
しかし,これでは Closureの恩恵が少ないです.これをもっと省略してみましょう.
省略ルール1
calc(n1: 2, n2: 5, operation: {(num1,num2)in num1 + num2})
一行!!!
ルールとしては,calc関数に引数と返り値の型は指定してあるのでClosure内で型を宣言する必要がないので消すことができます.
省略ルール2
そして二番目の省略のルール
ここまで来ればClosureは完璧でしょう.
Swiftでは、クロージャーは無名のパラメータ名を提供しています.
したがって、ここではパラメーター名としてnum1とnum2を指定していますが,
パラメータ名を無名にすることが可能なのでSwiftが準備しているパラメータ名
$を用いてパラメータ名を指定します.最初のパラメータを
$0
二番目のパラメータを
$1
としています.
つまり例を示すと,
calc(n1: 2, n2: 5, operation: {$0 + $1})
そして後で、これらのパラメーター名を参照して式を実行します。
ただし、これを行う代わりに、実際には匿名パラメーター名を使用できます。
最後の省略のルール
Swiftには、関数の最後のパラメーターがClosureである時,そのパラメータを省略することができるといったルールがあります.
これが最後のClosureです.全くもって美しい形になりました.
calc(n1: 2, n2: 5){$0 + $1}
Closureを書く前に()を閉じて{ Closure }を付け加えるだけで完成です.
いかがでしたか?Closureの凄さ伝わりましたか?
以上でClosureの説明を終わります.