Menu
Coddy logo textTech

値のキャプチャ

CoddyのSwiftジャーニー「ロジックとフロー」セクションの一部 — レッスン 40/56。

クロージャは、作成された時点のスコープ内にあった変数を記憶します。クロージャの本体は、後でそれらの変数を読み取ったり、さらには変更したりすることもできます。これは、周囲の関数がリターンした後でも可能です。これをキャプチャと呼びます。

func makeCounter() -> () -> Int {
    var count = 0
    return {
        count += 1
        return count
    }
}

let next = makeCounter()
print(next())                    // 1
print(next())                    // 2
print(next())                    // 3

makeCounter を呼び出すたびに新しい count が作成されるため、2つのカウンタが状態を共有することはありません。

let a = makeCounter()
let b = makeCounter()
print(a())                       // 1
print(b())                       // 1
print(a())                       // 2

キャプチャこそが、クロージャを通常の関数よりも強力なものにしている理由です。クロージャは状態を保持することができるからです。JavaScriptやPython、その他多くの言語でも、これと同じ仕組みを目にすることでしょう。

challenge icon

チャレンジ

中級

小さなカウンターファクトリを構築してください。

() -> Int 型のクロージャを返す関数 makeCounter(start: Int, step: Int) を定義してください。このクロージャを呼び出すたびに次の値が返されます。最初の呼び出しでは start を返し、次は start + step、その次は start + 2*step というように続きます。

入力から3つの整数 startstepn を読み取ります。startstep を使用してカウンターを構築し、それを n 回呼び出して、各結果をそれぞれの行に出力してください。

入力が 5 / 3 / 4 の場合、出力は以下のようになります:

5
8
11
14

チートシート

クロージャは、周囲のスコープから変数をキャプチャし、外部関数が終了した後でも状態を保持します。

func makeCounter() -> () -> Int {
    var count = 0
    return {
        count += 1
        return count
    }
}

let next = makeCounter()
print(next()) // 1
print(next()) // 2

ファクトリ関数を呼び出すたびに、独立したキャプチャ変数が作成されます。2つのカウンタが状態を共有することはありません。

自分で試してみよう

let start = Int(readLine()!)!
let step = Int(readLine()!)!
let n = Int(readLine()!)!

// TODO: 実行中の値を保持する makeCounter(start:step:) -> () -> Int を作成する
// その後、それを n 回呼び出して、各結果を出力する
quiz icon腕試し

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

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