クロージャを返す
CoddyのSwiftジャーニー「ロジックとフロー」セクションの一部 — レッスン 41/56。
makeCounter がクロージャを返すのを見ました。同じ手法を使って、設定可能な振る舞いを構築できます。一度パラメータを受け取り、それを何度も使用する関数を返します。
func multiplier(_ k: Int) -> (Int) -> Int {
return { n in n * k }
}
let triple = multiplier(3)
let tenfold = multiplier(10)
print(triple(4)) // 12
print(tenfold(4)) // 40返されるクロージャは k をキャプチャするため、各 multiplier(...) の呼び出しは、独自の k を持つまったく新しいクロージャを生成します。
このパターンは、Swiftにおける「ストラテジー」コードの核心です。設定を受け取りクロージャを返す関数を記述し、そのクロージャを map、filter、sorted(by:)、または関数型の値が期待されるその他の場所に渡します。
チャレンジ
中級2つのクロージャファクトリを作成してください:
greaterThan(_ k: Int) -> (Int) -> Bool: 引数がkより大きい場合にtrueを返す述語を返します。scaleBy(_ k: Int) -> (Int) -> Int: 引数にkを掛ける関数を返します。
以下の3行を読み込んでください:
- 整数
threshold - 整数
scale - カンマ区切りの整数リスト
nums
以下の3行を出力してください:
- しきい値(threshold)を超える数値(
greaterThanからのクロージャでフィルタリングしたもの)を,で連結したもの - 同じ数値をスケール(
scaleByでマップしたもの)し、,で連結したもの - 条件を満たした数値の個数
入力が 5 / 3 / 2,7,3,8,9 の場合、出力は以下のようになります:
7,8,9
21,24,27
3チートシート
クロージャファクトリは、パラメータをキャプチャし、それによって構成された新しいクロージャを返す関数です:
func multiplier(_ k: Int) -> (Int) -> Int {
return { n in n * k }
}
let triple = multiplier(3)
print(triple(4)) // 12呼び出しごとに、独自のkのキャプチャ値を保持する、まったく新しいクロージャが生成されます。返されたクロージャは、map、filter、sorted(by:)などに直接渡すことができます:
func greaterThan(_ k: Int) -> (Int) -> Bool {
return { n in n > k }
}
let nums = [2, 7, 3, 8, 9]
let filtered = nums.filter(greaterThan(5)) // [7, 8, 9]
let scaled = filtered.map(multiplier(3)) // [21, 24, 27]自分で試してみよう
let threshold = Int(readLine()!)!
let scale = Int(readLine()!)!
let nums = readLine()!.components(separatedBy: ",").map { Int($0)! }
// TODO: greaterThan, scaleBy; フィルタリングしてからマッピング; 結合して出力し、カウントを表示
このレッスンには短いクイズがあります。レッスンを始めて解答し、進捗を記録しましょう。