Menu
Coddy logo textTech

クロージャを返す

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における「ストラテジー」コードの核心です。設定を受け取りクロージャを返す関数を記述し、そのクロージャを mapfiltersorted(by:)、または関数型の値が期待されるその他の場所に渡します。

challenge icon

チャレンジ

中級

2つのクロージャファクトリを作成してください:

  • greaterThan(_ k: Int) -> (Int) -> Bool: 引数が k より大きい場合に true を返す述語を返します。
  • scaleBy(_ k: Int) -> (Int) -> Int: 引数に k を掛ける関数を返します。

以下の3行を読み込んでください:

  1. 整数 threshold
  2. 整数 scale
  3. カンマ区切りの整数リスト nums

以下の3行を出力してください:

  1. しきい値(threshold)を超える数値(greaterThan からのクロージャでフィルタリングしたもの)を , で連結したもの
  2. 同じ数値をスケール(scaleBy でマップしたもの)し、 , で連結したもの
  3. 条件を満たした数値の個数

入力が 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のキャプチャ値を保持する、まったく新しいクロージャが生成されます。返されたクロージャは、mapfiltersorted(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; フィルタリングしてからマッピング; 結合して出力し、カウントを表示
quiz icon腕試し

このレッスンには短いクイズがあります。レッスンを始めて解答し、進捗を記録しましょう。

ロジックとフローのすべてのレッスン