関数の最後の引数として関数にクロージャ式を渡す必要があって、かつクロージャ式が長い場合には、後置クロージャとして記述すると効果的です。後置クロージャは、サポートする関数呼び出しの丸括弧の外側(後ろ)に記述されるクロージャ式です。

func someFunctionThatTakesAClosure(closure: () -> Void) {
    // 関数本体
}

// 後置クロージャを使用せずに、この関数を呼び出す方法

someFunctionThatTakesAClosure({
    // クロージャの本体
})

// 後置クロージャを使用して、この関数を呼び出す方法

someFunctionThatTakesAClosure() {
    // 後置クロージャの本体
}

Closure Expression Syntax の文字列ソート用クロージャを、後置クロージャとして sort(_:) メソッドの丸括弧の外側に記述することができます。

reversed = names.sort() { $0 > $1 }

クロージャ式が関数やメソッドの唯一の引数で、そのクロージャ式を後置クロージャとする場合には、関数を呼び出すときに関数名やメソッド名の後に丸括弧 () を記述する必要はありません。

reversed = names.sort { $0 > $1 }

クロージャがインラインで 1 行に記述するには長すぎるときに、後置クロージャは最も効果的です。例として、Swift の Array 型には引数 1 つのクロージャ式を受け取る map(_:)メソッドがあります。クロージャは配列内の項目ごとに一度呼び出され、その項目にマッピングした別の(型が異なることもある)値を返します。マッピングの性質と戻り値の型は、指定するクロージャに委ねられています。

配列の各要素にクロージャを適用後、map(_:) メソッドは元の配列での対応する値と同じ順序で、マッピングした新しい値をすべて含む新しい配列を返します。

これ以降は、Int 値の配列を String 値の配列に変換する後置クロージャを受け取る map(_:) メソッドを使う方法です。配列 [16, 58, 510] は、新しい配列 ["OneSix", "FiveEight", "FiveOneZero"] を生成するために使用されます。

let digitNames = [
    0: "Zero", 1: "One", 2: "Two",   3: "Three", 4: "Four",
    5: "Five", 6: "Six", 7: "Seven", 8: "Eight", 9: "Nine"
]
let numbers = [16, 58, 510]

このコードは、整数値と英語名をマッピングする辞書を生成しています。また、文字列に変換される整数値の配列を定義しています。

クロージャ式を後置クロージャとして配列の map(_:) メソッドに渡すことで、String値の配列を生成するために配列 numbers を使用することができます。

let strings = numbers.map {
    (number) -> String in
    var number = number
    var output = ""
    while number > 0 {
        output = digitNames[number % 10]! + output
        number /= 10
    }
    return output
}
// strings は [String] 型と推論される
// その値は ["OneSix", "FiveEight", "FiveOneZero"]

map(_:) メソッドは配列内の各項目ごとに一度クロージャ式を呼び出します。マップされる配列内の値から型を推論できるため、クロージャの入力パラメータ number の型を指定する必要はありません。

この例では、変数 number はクロージャの number パラメータの値で初期化されているため、値をクロージャ本体で変更することができます。(関数およびクロージャのパラメータは常に定数です。)また、マップされる配列に格納される型を示すために、クロージャ式に戻り値の型 String を指定しています。

クロージャ式は、呼び出されるたびに文字列 output を構築します。剰余演算 (number % 10) を使用して number の最後の桁の数値を算出し、辞書 digitNames から適切な文字列を調べるためにこの数値を使用します。文字列表現を生成するために、1 以上の整数をこのクロージャに使用することができます。

NOTE
辞書のサブスクリプトは、キーが存在しない場合には辞書探索が失敗することを示すオプショナル値を返すため、辞書 digitNames のサブスクリプトを呼び出すときにエクスクラメーションマーク (!) を付けます。上の例では、number % 10 が常に辞書 digitNamesの有効なサブスクリプトキーであることが確実なため、サブスクリプトが返すオプショナル値に格納された String 値を強制的にアンラップするために、エクスクラメーションマークを使用しています。

辞書 digitNames から取得された文字列は、効果的に逆順で数値の文字列バージョンを構築するために、output の前に追加されています。(式 number % 10 は、16 を 6 に、58を 8 に、510 を 51 にします。)

そして、変数 number は 10 で割られています。整数であるため割り算で切り捨てられ、16 が 1 に、58 が 5 に、510 が 51 になります。

number が 0 になるまで処理が繰り返され、文字列 output がクロージャから返され、map(_:) メソッドによって配列に追加されます。

上で見た後置クロージャシンタックスの使用例は、map(_:) メソッドの丸括弧でクロージャ全体を囲む必要がなく、関数のすぐ後にクロージャの機能をすっきりと記述してしています。


Portions of this page are translations based on work created and shared by Apple and used according to terms described in the Creative Commons Attribution 4.0 International License.