【Swift】クロージャの使い方。名前の無い関数を作る。(Swift 2.1、XCode 7.2)

2020年6月16日

クロージャとは

クロージャとは、名前を付けずに定義する関数のことを言う。変数や引数に関数の中身を直接代入するような使い方をする。

クロージャは以下のように定義する。関数名が無いのと、inがあるのが通常の関数とは異なる。for-inのinを連想して混乱するが、それとは別ものである。

 

具体的なコードを見てみよう。以下のコードは変数にクロージャを代入する例。「変数名(価格、個数)」でクロージャを実行すると、価格×個数の結果が返ってくる。

 

クロージャの書き方を簡略化する

クロージャは変数や引数に関数の中身を直接記述するので、中身が長いとソースが読みづらくなる。そのため、コードを簡略化できるルールが備わっている。

①「処理が1文の場合はreturnを省略できる」

上記コードは処理が1文しか無いのでreturnを省略して以下のコードのように簡略化できる。

 

ちなみに以下のコードのように、処理が複数文あるのにreturnを省略するとエラーが発生する。

 

②「処理が1文の場合は戻り値の型を省略できる」

上記コードは処理が1文しか無いので戻り値を省略して以下のコードのように簡略化できる。

 

ちなみに、以下のコードのように処理が複数文あるのに戻り値を省略するとエラーが発生する。

 

③「型が分かっている場合は省略できる」

以下のコードのように型を指定してクロージャの変数を宣言すれば、クロージャの中で型を記述しなくても良い。

 

④「引数が1個の場合は引数を囲む括弧を省略できる」

以下のコードのように、クロージャに与える引数が1個の場合は、引数を囲む括弧は省略できる。

 

⑤「引数名にこだわりがなければ引数名を省略できる」

引数名にこだわりが無いのであれば、第1、第2引数をそれぞれ$0、$1とし、inを省略して以下のコードのように短縮できる。スッキリ極まりない。

クロージャを引数にして関数を呼び出す

次に、クロージャを引数にして関数を呼び出す例を見てみよう。以下のコードは、価格、個数、クロージャを引数に関数を呼び出し、関数の中でクロージャを実行するものである。

 

先ほどの例と同様に、上記コードを簡略化すると以下のようになる。

クロージャの使いどころ

クロージャを学んで思うことは「クロージャを使うより、関数を使った方が分かりやすいのでは?」の人が多いのではないだろうか。

確かに、変数や引数に唐突に入りこんできて一見何をしているのか分かりづらいクロージャを使ったロジックを考えるよりは、関数を使ってコーディングしたほうがソースの可読性も上がり、デバッグがしやすいはずだ。

アプリ開発で絶対にここはクロージャを使った作りにした方が良いという利点が見つかれば、今後の記事で紹介することにする。

ただし、細かいところでクロージャを使う状況はある。例えば、コレクションの並び替えや、抽出などで自前の比較条件を指定するような場合である。

以下のコードは配列から3で割り切れる値を抽出するものである。fileterメソッドの引数にクロージャを与えてフィルタリングを行っている。クロージャは、配列の値を3で割った余りが0になればtrue、0にならなければfalseを返す。filterメソッドはクロージャがtrueと判定したものを抽出条件を満たした値と判断する。

 

上記のコードを簡略化すると以下のコードになる。スッキリした。

 

以下のコードはsortメソッドを利用して配列のすべてのデータを降順に並び替えた配列を取得する例である。クロージャでは配列の2つの要素の比較条件を記述する。

 

以下のコードは、mapメソッドを利用して配列のすべてのデータに7を足した配列を取得する例である。クロージャでは配列の値に7を加算している。

 

以下のコードは、reduceメソッドを利用して配列のすべてのデータを合計する例である。reduceメソッドの第1引数には初期値、第2引数にはクロージャを与える。