Swift による iOS 開発入門

ホーム > Swift の基本 > クロージャ

クロージャ

ここでは Swift のクロージャ (closures) について学びます。

Swift でのクロージャは三つの形式があります。

ひとつはグローバル関数 (global functions)。

これは名前付きで、値をキャプチャしないクロージャといえます。

二つ目はネストされた関数 (nested functions)。

これは名前付きで、関数を包含するブロックにおける値をキャプチャするクロージャです。

三つ目はクロージャ式 (closure expressions) です。

これは名前無し、かつ、そのコンテキストにおける値をキャプチャするものです。

始めの二つについては、「関数」をみてください。このページでは三つ目のクロージャ式について説明します。

クロージャ式

クロージャ式 は次の形式で記述できます。

{ (引数1: 型1, 引数2 : 型2, ...) -> 戻り値の型 in
	return 戻り値
}

具体例を取り上げて説明します。

配列の sort 関数は、「配列の二つの要素を受取り、一つめの引数と二つめの引数がソートしたい順序にあるときに True、そうでない場合に False を返す関数」 を引数として受取ります。

func f( i : Int, j : Int ) -> Bool {
	return i < j
}

var nums = [ 3, 10, 1, 5, 2 ]
nums.sort( f ) // [1, 2, 3, 5, 10]

ここで関数名の f というのは全く重要ではありませんので、名前無しのクロージャ式で記述してみましょう。 クロージャ式を使うと次のように書けます。

var nums = [ 3, 10, 1, 5, 2]
nums.sort( { ( i : Int, j : Int ) -> Bool in
	return i < j
})

一行で終わるときは in の後で改行する必要は無いので、改行をやめると次のようになります。

nums.sort( { ( i : Int, j : Int ) -> Bool in return i < j })

コードはかなり短くなりましたね。

さらに、nums は Int の配列なので、クロージャ内で記述している Int という型はわかりますので省略できます。さらに、return は比較した結果 (True または False) を 返しているのでこれも Bool しかなりえず型がわかります。

このように全て型がわかる場合は、型の指定も省略できます。すると上記の記述は次のようになります。

nums.sort( { i , j in return i < j })

さらに、単一の式で表されるクロージャでは、暗黙的にその値が返るので return も省略できます。したがって、次のようになります。

nums.sort( { i , j in i < j })

Swift ではインラインクロージャでは自動的に引数の省略名が作成されます。最初の引数から $0, $1, $2, ... という調子です。

これを利用すると、上記の i, j という宣言も不要となり、次のようになります。

nums.sort( { $0 < $1 })

始めの書き方と比較すると、圧倒的に記述が短く簡潔になりましたね。

Playground で動作確認すると、スクリーンショットのように確かにソートされたことがわかります。

トレーリング・クロージャ

関数のパラメータリストの最後にクロージャ式が引数となっているときは、そのクロージャ式を関数呼び出しの後に続けて書くことができます

例えば、先の sort の例では、クロージャ式が唯一の (よって、最後の) 引数です。従って、クロージャを外に出して次のように書けます。

nums.sort() { $0 < $1 }

このように関数の後に続けて記述したクロージャを、トレーリング・クロージャ (trailing closures) といいます。

クロージャの本体の記述が長くなる場合には、このように記述したほうが可読性が上がる場合があります。

ホーム > Swift の基本 > クロージャ