Swift 5.8 日本語化計画 : Swift 5.8


関数(Functions)


関数を定義して呼び出し、それらの引数にラベルを付け、それらの戻り値を使用します。

関数 は、特定のタスクを実行する自己完結型のコードの塊です。それが何をするか識別するため関数に名前を与え、この名前は必要なときにそのタスクを実行する関数を "呼び出す" ために使用されます。


Swift の統一関数の構文は、パラメータ名のない単純な C スタイルの関数から、各パラメータに名前と引数のラベルを付けた複雑な Objective-C スタイルのメソッドまで、全ての物を表現するのに十分な柔軟性があります。パラメータは、関数呼び出しを簡素化するためにデフォルト値を提供することができ、入出力のパラメータとして渡すことができ、関数がその実行を一旦完了すると渡された変数を変更します。


Swift 内のすべての関数には、関数のパラメータ型と戻り値の型からなる型があります。それが簡単に他の関数へのパラメータとして関数を渡す事ができ、関数から関数を返せるので Swift の他の型のように、この型を使用できます。入れ子にされた関数の範囲内で便利な機能をカプセル化するために、他の関数内で関数をもまた記述することができます。



関数の定義と呼び出し


あなたが関数を定義するときは、必要に応じて パラメータ として知られる、入力として関数が取る、1つ以上の、名前を付けた型付きの値を定義できます。また、必要に応じて、それが行われた時、その 戻り値の型 として知られる、関数が出力として渡す値の型を定義できます。


すべての関数は、関数が実行するタスクを記述する 関数名 を持っています。関数を使用するには、その名前でその関数を "呼び出し"、関数のパラメータの型と一致する入力値、(引数 として知られています)を渡します。関数の引数は、常に、関数のパラメータリストと同じ順序で提供されなければなりません。


以下の例の関数は、greet(person:) と呼ばれ、というのもそれが行う事だからですが、入力として人の名前を取り、その人のための挨拶を返します。これを実現するために、一つの入力パラメータである、 person と呼ばれる String 値を定義し、その人のための挨拶を含むことになる String の戻り値の型を定義します。


  1. func greet(person: String) -> String {
  2. let greeting = "Hello, " + person + "!"
  3. return greeting
  4. }


この情報はすべて、func キーワードが接頭辞として付いている関数の 定義 に巻き込まれています。
戻り矢印 -> (右山括弧が続くハイフン) で、返すべき型の名前が続き、関数の戻り値の型を示しています。


定義は、関数がする事、関数が受け取るように期待するもの、そしてそれが行われたときに返すものを説明します。コードの他の場所から明確に呼び出せるように関数を定義すると、それが容易になります:


  1. print(greet(person: "Anna"))
  2. // prints "Hello, Anna!"
  3. print(greet(person: "Brian"))
  4. // prints "Hello, Brian!"


greet(person: "Anna") のような、person 引数ラベルの後に String 値をそれに渡すことで greet(person:) 関数を呼び出して下さい。関数は、String 型の値を返しますので、上記のように、その文字列を印刷し、その戻り値を見るには print(_:separator:terminator:) 関数への呼び出しの中に greet(person:) は包み込まれています。


注意: print(_:separator:terminator:) 関数は、最初の引数のラベルを持っておらず、それらはデフォルト値を持っているので、その他の引数はオプションです。関数の構文上のこれらのバリエーションは、以下の 関数引数のラベルとパラメータ名デフォルトのパラメータ値 に議論されています。


greet(person:) 関数の本体は、greeting と呼ばれる新しい String 定数を定義し、簡単な挨拶をそれに設定することで始まります。この挨拶は、その後 return キーワードを使用して関数の外に渡されます。return greeting というコードの行では、この関数はその実行を終了し、greeting の現在の値を返します。


異なる入力値で greet(person:) 関数を複数回呼び出すことができます。上記の例では、"Anna" の入力値、および "Brian" の入力値で呼び出された場合に何が起きるかを示しています。関数は、それぞれの場合にぴったりとした挨拶を返します。


この関数の本体を簡素化して、メッセージの作成と return 文を組み合わせて1行にします:


  1. func greetAgain(person: String) -> String {
  2. return "Hello again, " + person + "!"
  3. }
  4. print(greetAgain(person: "Anna"))
  5. // prints "Hello again, Anna!"


関数のパラメータと戻り値


関数のパラメータと戻り値は、Swift では非常に柔軟です。一つの名前のないパラメータを持つ簡単なユーティリティ関数から表情豊かなパラメータ名と、様々なパラメータオプションを持つ複雑な関数まで何でも定義することができます。



パラメータなしの関数


関数は、入力パラメータを定義する必要はありません。ここでは、それが呼ばれるたびに常に同じ String メッセージを返す、入力パラメータのない関数の例を挙げます。


  1. func sayHelloWorld() -> String {
  2. return "hello, world"
  3. }
  4. print(sayHelloWorld())
  5. // Prints "hello, world"

関数の定義はそれが全くパラメータを取らないにもかかわらず、関数名の後の括弧をまだ必要とします。関数が呼び出されたときに、関数名にも括弧の空のペアが続きます。



複数パラメータを持つ関数


関数は、関数の括弧内にカンマで区切って書かれた、複数の入力パラメータを持つことができます。


以下の関数は、人の名前と、それらがすでに入力として挨拶されたかを取り、そしてその人のための適切な挨拶を返します。


  1. func greet(person: String, alreadyGreeted: Bool) -> String {
  2. if alreadyGreeted {
  3. return greetAgain(person: person)
  4. } else {
  5. return greet(person: person)
  6. }
  7. }
  8. print(greet(person: "Tim", alreadyGreeted: true))
  9. // Prints "Hello again, Tim!"


greet(person:alreadyGreeted:) 関数を呼び出すのに person とラベルされた String 型の引数値と alreadyGreeted とラベルされた Bool 引数値の両方をカンマで区切って括弧内に入れ渡します。以前のセクションで示した greet(person:) 関数とはこの関数は異なることに注意してください。両方の関数とも greet で始まる名前を持っていますが、greet(person:alreadyGreeted:) 関数は 2 つの引数を取りますが、greet(person:) 関数は一つだけを取ります。



戻り値なしの関数


関数は戻り値型を定義する必要はありません。ここでは greet(person:) 関数の一つのバージョンを示しますが、それは値を返すよりも、独自の String 値を印刷します。


  1. func greet(person: String) {
  2. print("Hello, \(person)!")
  3. }
  4. greet("Dave")
  5. // prints "Hello, Dave!"


戻り値を返す必要はないので、関数の定義は、戻り矢印 (->) や戻り値の型を含んでいません。


注意: 厳密に言えば、greet(person:) 関数のこのバージョンは戻り値を定義していないにもかかわらず、まだ値を返 します。定義された戻り値の型のない関数は Void 型の特殊な値を返します。これは、単に空のタプルで、() のように書くことができます。


関数が呼び出されたときにその戻り値は無視することができます:


  1. func printAndCount(string: String) -> Int {
  2. print(string)
  3. return string.count
  4. }
  5. func printWithoutCounting(string: String) {
  6. let _ = printAndCount(string:string)
  7. }
  8. printAndCount(string:"hello, world")
  9. // prints "hello, world" and returns a value of 12
  10. printWithoutCounting(string:"hello, world")
  11. // prints "hello, world" but does not return a value


最初の関数、printAndCount(string:) は、文字列を印刷し、その後 Int としてその文字数を返します。第二の関数、printWithoutCounting(string:) は、最初の関数を呼び出しますが、その戻り値を無視します。第二の関数が呼び出されると、メッセージがまず最初の関数により印刷されますが、戻り値は使用されません。



注意: 戻り値は無視できますが、値を返すという関数は常にそうしなければなりません。定義された戻り値の型を持つ関数では、値を返す事なしに関数の一番最後から制御が飛び出すことを許されず、そうしようとするとコンパイル時エラーになります。


複数の戻り値を持つ関数


1 つの複合した戻り値の一部として複数の値を返すように関数の戻り値の型としてタプル型を使用できます。


以下の例では、Int 型の値の配列の最小と最大の数字を見つける、minMax(array:) という関数を定義しています。


  1. func minMax(array: [Int]) -> (min: Int, max: Int) {
  2. var currentMin = array[0]
  3. var currentMax = array[0]
  4. for value in array[1..<array.count] {
  5. if value < currentMin {
  6. currentMin = value
  7. } else if value > currentMax {
  8. currentMax = value
  9. }
  10. }
  11. return (currentMin, currentMax)
  12. }


minMax(array:) 関数は、2つの Int 値を含むタプルを返します。関数の戻り値を照会するとき、名前でアクセスできるように、これらの値は、minmax のラベルが付いています。


minMax(array:) 関数の本体は、配列内の最初の整数の値に currentMincurrentMax という2つの作業変数を設定することによって開始します。その後関数は、残りの配列の値がそれぞれ currentMincurrentMax の値より小さいか大きいかを繰り返し確認します。最後に、全体の最小値と最大値を、2つの Int 値のタプルとして返します。


タプルのメンバーの値が関数の戻り値の型の一部として命名されているので、それらは最小値と最大値に基づいた値を取得するために、ドット構文を使用してアクセスできます:


  1. let bounds = minMax(array: [8, -6, 2, 109, 3, 71])
  2. print("min is \(bounds.min) and max is \(bounds.max)")
  3. // prints "min is -6 and max is 109"


自分の名前が既に関数の戻り値の型の一部として指定されているため、タプルのメンバーは、タプルが関数から返された時点では名前を付ける必要はないことに注意してください。



optional のタプル型の戻り値


関数から返されるタプル型が全体のタプルで "値がない" 可能性がある場合は、全体のタプルが nil になりうるという事実を反映して、optional のタプル型の戻り値を使用できます。(Int, Int)?(String, Int, Bool)? のように、タプル型の閉じ括弧の後に疑問符を書くことによって、optional のタプルの戻り値の型を書いて下さい。



注意: (Int, Int)? のような optional のタプル型は、(Int?, Int?) のような optional 型を含むタプルとは異なります。Optional のタプル型では、タプル内の個々の値ではなく、全体のタプルが optional です。


上記の minMax(array:) 関数は、二つの Int 値を含むタプルを返します。しかし、関数は、それが渡される配列上の安全性チェックを何ら実行しません。array の引数が空の配列、つまり、上記で定義された minMax(array:) 関数を含む場合は、array[0] にアクセスしようとしたとき、実行時エラーを引き起こします。


この"空の配列"を安全に処理するには、optional のタプルの戻り値型を持つ minMax(array:) 関数を記述し、配列が空の場合に、nil の値を返すようにします:


  1. func minMax(array: [Int]) -> (min: Int, max: Int)? {
  2. if array.isEmpty { return nil }
  3. var currentMin = array[0]
  4. var currentMax = array[0]
  5. for value in array[1..<array.count] {
  6. if value < currentMin {
  7. currentMin = value
  8. } else if value > currentMax {
  9. currentMax = value
  10. }
  11. }
  12. return (currentMin, currentMax)
  13. }


minMax(array:) 関数のこのバージョンが、実際のタプル値または nil を返すかどうかを確認するために、optional の結合を使用できます。


  1. if let bounds = minMax([8, -6, 2, 109, 3, 71]) {
  2.        print("min is \(bounds.min) and max is \(bounds.max)")
  3. }
  4. // prints "min is -6 and max is 109"


暗黙の戻り値を持つ関数


関数の本体全体が単一の式である場合、関数はその式を暗黙的に返します。たとえば、以下の両方の関数の動作は同じです。


  1. func greeting(for person: String) -> String {
  2. "Hello, " + person + "!"
  3. }
  4. print(greeting(for: "Dave"))
  5. // Prints "Hello, Dave!"
  6. func anotherGreeting(for person: String) -> String {
  7. return "Hello, " + person + "!"
  8. }
  9. print(anotherGreeting(for: "Dave"))
  10. // Prints "Hello, Dave!"


greeting(for:) 関数の完全な定義は、それが返す挨拶メッセージです。つまり、この短い形式を使用できる事を意味します。anotherGreeting(for:) 関数は、長い関数のように return キーワードを使用して、同じ挨拶メッセージを返します。ただ 1 つの return 行として記述する全ての関数は、return を省略できます。


ゲッタ宣言の省略形 で見るように、プロパティ getter は暗黙的な return を使用することもできます。


注意:暗黙の戻り値として記述したコードは、何らかの値を返す必要があります。たとえば、print(13) を暗黙の戻り値として使用することはできません。ただし、Swift は暗黙的な return が発生しないことを認識しているため、FatalError("Oh no!") のように決して return のない関数を暗黙的な戻り値として使用できます。


関数引数のラベルとパラメータ名


各関数のパラメータは、引数のラベルパラメータ名 の両方を持っています。引数のラベルは関数を呼び出すときに使用されます。各引数は、関数呼び出しでその前にその引数のラベルが書かれます。パラメータ名は、関数の実装に使用されます。デフォルトでは、パラメータは、それらの引数のラベルとして、それらのパラメータ名を使用します。


  1. func someFunction(firstParameterName: Int, secondParameterName: Int) {
  2. // In the function body, firstParameterName and secondParameterName
  3. // refer to the argument values for the first and second parameters.
  4. }
  5. someFunction(firstParameterName: 1, secondParameterName: 2)


すべてのパラメータは、独自の名前を持っていなければなりません。複数のパラメータは、同じ引数ラベルを持つことが可能ですが、一意の引数ラベルは、あなたのコードを読みやすくするのに役立ちます。



引数のラベルの指定


パラメータ名の前に引数のラベルを、スペースで区切って書いて下さい。


  1. func someFunction(argumentLabel parameterName: Int) {
  2. // In the function body, parameterName refers to the argument value
  3. // for that parameter.
  4. }


ここで、人の名前と出身地を取り、挨拶を返す greet(person:) 関数のバリエーションを挙げましょう。


  1. func greet(person: String, from hometown: String) -> String {
  2. return "Hello \(person)! Glad you could visit from \(hometown)."
  3. }
  4. print(greet(person: "Bill", from: "Cupertino"))
  5. // Prints "Hello Bill! Glad you could visit from Cupertino."


引数のラベルの使用は、関数が表現力豊かで、文章のような方法で、呼び出すことができるようにし、まだ関数本体の意図を明確にし、読みやすくします。



引数ラベルの省略


パラメータに引数のラベルをしたくない場合は、そのパラメータの明示的な引数のラベルの代わりに、アンダースコア(_) を書きます。


  1. func someFunction(_ firstParameterName: Int, secondParameterName: Int) {
  2. // In the function body, firstParameterName and secondParameterName
  3. // refer to the argument values for the first and second parameters.
  4. }
  5. someFunction(1, secondParameterName: 2)


パラメータに引数のラベルがある場合は、関数を呼び出すときには、引数はラベル付け しなければなりません



デフォルトのパラメータ値


そのパラメータの型の後にパラメータに値を割り当てることによって、関数内の任意のパラメータに デフォルト値 を定義できます。デフォルト値が定義されている場合は、関数を呼び出すとき、そのパラメータを省略できます。


  1. func someFunction(parameterWithoutDefault: Int, parameterWithDefault: Int = 12) {
  2. // If you omit the second argument when calling this function, then
  3. // the value of parameterWithDefault is 12 inside the function body.
  4. }
  5. someFunction(parameterWithoutDefault: 3, parameterWithDefault: 6)
    // parameterWithDefault is 6
  6. someFunction(parameterWithoutDefault: 4) // parameterWithDefault is 12


デフォルト値を持つパラメータの前に、関数のパラメータリストの先頭にデフォルト値のないパラメータを置きます。デフォルト値を持たないパラメータは、関数の意味にとっては通常、より重要であり、それらを最初に書くことは、デフォルトパラメータが省略されているかどうかに関係なく、同じ関数が呼び出されていることの認識を容易にします。



可変引数パラメータ


可変引数のパラメータ は、指定された型のゼロ個以上の値を受け入れます。関数が呼び出されたとき、入力された値の様々な数をパラメータに渡すことができるように指定するには、可変引数のパラメータを使用して下さい。パラメータの型名の後に3つのピリオド文字(...)を挿入することによって、可変引数のパラメータを書くことができます。


可変引数のパラメータに渡された値は適切な型の配列として、関数の本体内で利用できるようになります。例えば、Double... の型の numbers と言う名の可変引数のパラメータは、[Double] 型の numbers という定数の配列として関数の本体内で使用可能になります。


以下の例は、任意の長さの数字のリストについて、(平均 として知られている)算術平均 を計算します。


  1. func arithmeticMean(_ numbers: Double...) -> Double {
  2. var total: Double = 0
  3. for number in numbers {
  4. total += number
  5. }
  6. return total / Double(numbers.count)
  7. }
  8. arithmeticMean(1, 2, 3, 4, 5)
  9. // returns 3.0, which is the arithmetic mean of these five numbers
  10. arithmeticMean(3, 8.25, 18.75)
  11. // returns 10.0, which is the arithmetic mean of these three numbers


関数は、複数の可変個パラメータを持てます。可変引数パラメーターの後に続く最初のパラメーターには、引数ラベルがなければなりません。引数ラベルにより、どの引数が可変引数パラメーターに渡され、どの引数が可変引数パラメーターの後に続くパラメーターに渡されるかが明確になります。



In-Out パラメータ


関数のパラメータは、デフォルトでは定数です。その関数の本体内から関数パラメータの値を変更しようとすると、コンパイル時エラーになります。これは、あなたが誤ってパラメータの値を変更できないことを意味します。関数でパラメータの値を変更したい場合や、関数呼び出しが終了した後にそれらの変更を持続したい場合は、代わりに in-out パラメータ としてそのパラメータを定義します。


パラメータの型の直前に inout キーワードを書くことによって、in-out パラメータを記述します。in-out パラメータが関数 内(in) に渡された値は、関数によって変更されており、元の値を置き換えるために関数の 外(out) に戻されます。in-out パラメータの動作と関連するコンパイラの最適化についての詳細は、In-Out パラメータ を参照してください。


in-out パラメータの引数としては変数だけを渡すことができます。定数およびリテラル値は変更できないので、定数またはリテラル値は引数として渡すことはできません。それが関数によって変更されうることを示すために、in-out パラメータに引数として渡すときには、変数の名前の直前にアンパサンド(&)を置いてください。



注意: in-out パラメータはデフォルト値を持つことができません。また可変引数のパラメータは inout としてマークすることはできません。


ここで、swapTwoInts(_:_:) と言う関数の例を示しますが、それには ab と言う2つの in-out 整数パラメータがあります。


  1. func swapTwoInts(_ a: inout Int, _ b: inout Int) {
  2. let temporaryA = a
  3. a = b
  4. b = temporaryA
  5. }


swapTwoInts(_:_:) 関数は単に b の値を a に、および a の値を b と交換します。この関数は、temporaryA と呼ばれる一時的な定数に a の値を保存し、ab の値を代入し、次に temporaryAb を代入することで、この交換を実行します。


それらの値を交換するのに Int 型の2つの変数を持つ swapTwoInts(_:_:) 関数を呼び出すことができます。それらは swapTwoInts(_:_:) 関数に渡されたとき someIntanotherInt の名前はアンパサンド(&) が付いていることに注意してください:


  1. var someInt = 3
  2. var anotherInt = 107
  3. swapTwoInts(&someInt, &anotherInt)
  4. print("someInt is now \(someInt), and anotherInt is now \(anotherInt)")
  5. // prints "someInt is now 107, and anotherInt is now 3"


上記の例では、それらは元々関数の外で定義されていたにもかかわらず、someIntanotherInt の元の値が swapTwoInts(_:_:) 関数によって変更されていることを表しています。


注意: in-out パラメータは、関数から値を返すのと同じではありません。上記の swapTwoInts の例では、戻り値やその型を定義していませんが、それは someIntanotherInt の値を変更します。in-out パラメータは、関数が関数本体の範囲外に効果を持つようにするための代替方法です。


関数型


すべての関数は、パラメータの型と関数の戻り値の型からなる特定の 関数型 を有します。


例えば:


  1. func addTwoInts(_ a: Int, _ b: Int) -> Int {
  2. return a + b
  3. }
  4. func multiplyTwoInts(_ a: Int, _ b: Int) -> Int {
  5. return a * b
  6. }


この例では、addTwoIntsmultiplyTwoInts と言う2つの単純な数学関数を定義しています。これらの関数は、それぞれ2つの Int 値をとり、適切な数学的演算を行った結果である Int 値を返します。


これらの関数の両方の型は (Int, Int) -> Int です。これは次のように読むことができます:


「2つのパラメータ、両方とも Int 型を持ち、Int 型の値を返す関数です。」


ここでは別の例を挙げ、パラメータも戻り値もない関数を考えます。


  1. func printHelloWorld() {
  2. print("hello, world")
  3. }


この関数の型は ()-> Void、または「パラメータのない、Void を返す関数」です。


関数型の使用


ちょうど Swift の他の型のように関数型を使用できます。たとえば、定数または変数は関数型に定義でき、その変数に適切な関数を割り当てることができます。


var mathFunction: (Int, Int) -> Int = addTwoInts



これは次のように読むことができます:


mathFunction という変数を定義し、それは『2つの Int 値をとる関数で、Int 値を返す。』という型を持っています。この新しい変数に addTwoInts と言う関数を参照するように設定します。」


addTwoInts(_:_:) 関数は mathFunction 変数と同じ型を持つので、この代入は、Swift の型チェッカーで許可されます。


これで、mathFunction と言う名前で代入された関数を呼び出すことができます。


  1. print("Result: \(mathFunction(2, 3))")
  2. // prints "Result: 5"


同じ一致する型を持つ異なる関数を、非関数型の場合と同様に、同じ変数に割り当てることができます。


  1. mathFunction = multiplyTwoInts
  2. print("Result: \(mathFunction(2, 3))")
  3. // prints "Result: 6"


他の型と同じように、定数または変数に関数を割り当てるときには関数型を推論する事を Swift に任せることができます:


  1. let anotherMathFunction = addTwoInts
  2. // anotherMathFunction is inferred to be of type (Int, Int) -> Int


パラメータ型としての関数型


(Int, Int) -> Int のような関数型を別の関数のパラメータ型として使用できます。これで、関数が呼び出されたときに提供するため関数の呼び出し元に関数の実装のいくつかの側面を任せることができます。


ここでは上述した数学関数の結果を印刷する例を示します。


  1. func printMathResult(_ mathFunction: (Int, Int) -> Int,_ a: Int,_ b: Int) {
  2. print("Result: \(mathFunction(a, b))")
  3. }
  4. printMathResult(addTwoInts, 3, 5)
  5. // prints "Result: 8"


この例では、3つのパラメータのある printMathResult(_:_:_:) という関数を定義しています。最初のパラメータは mathFunction と呼ばれ、(Int, Int) -> Int 型のものです。この最初のパラメータの引数としてその型の関数をどれでも渡すことができます。2番目と3番目のパラメータは、ab と呼ばれ、両方共 Int 型です。これらは用意された数学関数のための2つの入力値として使用されます。


printMathResult(_:_:_:) が呼び出されると、それは addTwoInts(_:_:) 関数を渡され、整数値 35 を渡されます。それは、用意された関数を 35 の値で呼び出し、結果の 8 を印刷します。


printMathResult(_:_:_:) の役割は、適切な型の数学関数への呼び出しの結果を印刷することです。その関数の実装が実際にどうなっているかは問題でなく、関数が正しい型であることだけが重要です。これは、型安全の方法で、関数の呼び出し元に、その機能の一部を渡すのを printMathResult(_:_:_:) に可能にします。


戻り値の型としての関数型


別の関数の戻り値の型として関数型を使用できます。返す関数の、戻り矢印 (->) の直後に完全な関数型を書くことで、これを行えます。


次の例では、stepForward(_:)stepBackward(_:) と言う簡単な関数を2つ定義しています。stepForward(_:) 関数はその入力値より一つだけ大きいものを返し、stepBackward(_:) 関数は、その入力値より一つだけ小さい値を返します。どちらの関数も (Int) -> Int の型です。


  1. func stepForward(_ input: Int) -> Int {
  2. return input + 1
  3. }
  4. func stepBackward(_ input: Int) -> Int {
  5. return input - 1
  6. }


ここで、chooseStepFunction(backward:) と言う関数を考え、それは戻り値の型が (Int) -> Int 型の関数です。 chooseStepFunction(backward:) 関数は、backward と言うブール値のパラメータに基づいて stepForward(_:) 関数あるいは stepBackward(_:) 関数を返します。


  1. func chooseStepFunction(backwards: Bool) -> (Int) -> Int {
  2. return backwards ? stepBackward : stepForward
  3. }


これで、一方向または他の方向に進む関数を取得するために chooseStepFunction(backward:) を使用できます。


  1. var currentValue = 3
  2. let moveNearerToZero = chooseStepFunction(backward: currentValue > 0)
  3. // moveNearerToZero now refers to the stepBackward() function


上述の例では、currentValue と言う変数をゼロに近づけるために正か負のステップのどちらが必要であるかを判定します。currentValue3 の初期値を持っており、それは currentValue > 0true を返す事を意味し、 chooseStepFunction(backward:)stepBackward(_:) 関数を返します。返される関数への参照は、 moveNearerToZero と言う定数に保存されます。


今や moveNearerToZero は正しい関数を参照しており、カウントをゼロにするために使用できます。


  1. print("Counting to zero:")
  2. // Counting to zero:
  3. while currentValue != 0 {
  4.        print("\(currentValue)... ")
  5.        currentValue = moveNearerToZero(currentValue)
  6. }
  7. print("zero!")
  8. // 3...
  9. // 2...
  10. // 1...
  11. // zero!


入れ子になった関数


この章でこれまでお見せした関数はすべて、グローバルな範囲で定義されている グローバルな関数 の例でした。他の関数の本体内に関数を定義することもでき、入れ子になった関数 として知られています。


入れ子になった関数は、デフォルトでは外の世界から隠されていますが、それらを取り囲む関数で呼び出され、使用することができます。取り囲んでいる関数は、また入れ子になった関数の一つを返すこともでき、入れ子になった関数が別の範囲内で使用できるようにできます。


上記の chooseStepFunction(backward:) の例を書き換えて、入れ子になった関数を使用して返すことができます。


  1. func chooseStepFunction(backward: Bool) -> (Int) -> Int {
  2. func stepForward(input: Int) -> Int { return input + 1 }
  3. func stepBackward(input: Int) -> Int { return input - 1 }
  4. return backward ? stepBackward : stepForward
  5. }
  6. var currentValue = -4
  7. let moveNearerToZero = chooseStepFunction(backward: currentValue > 0)
  8. // moveNearerToZero now refers to the nested stepForward() function
  9. while currentValue != 0 {
  10. print("\(currentValue)... ")
  11. currentValue = moveNearerToZero(currentValue)
  12. }
  13. print("zero!")
  14. // -4...
  15. // -3...
  16. // -2...
  17. // -1...
  18. // zero!

前:フロー制御 次:クロージャ
















トップへ












トップへ












トップへ












トップへ
目次
Xcode の新機能

Swift について
Swift と Cocoa と Objective-C (obsolete)
Swift Blog より (obsolete)

SwiftLogo
  • Swift 5.8 全メニュー


  • Swift へようこそ

  • Swift 言語のガイド
  • 基本演算子
  • 文字列と文字
  • コレクション型
  • フロー制御
  • 関数
  • クロージャ
  • 列挙型
  • 構造体とクラス
  • プロパティ
  • メソッド
  • サブスクリプト
  • 継承
  • 初期化
  • デイニシャライザ
  • Optional の連鎖
  • エラー処理
  • 同時実行
  • 型キャスト
  • ネストした型
  • 拡張機能
  • プロトコル
  • ジェネリック(汎用)
  • 不透明な型
  • 自動参照カウント
  • メモリの安全性
  • アクセス制御
  • 高度な演算子

  • 言語リファレンス

  • マニュアルの変更履歴













  • トップへ












    トップへ












    トップへ












    トップへ












    トップへ












    トップへ












    トップへ












    トップへ












    トップへ












    トップへ












    トップへ












    トップへ












    トップへ












    トップへ












    トップへ












    トップへ












    トップへ












    トップへ












    トップへ












    トップへ












    トップへ












    トップへ












    トップへ












    トップへ












    トップへ












    トップへ












    トップへ












    トップへ












    トップへ












    トップへ












    トップへ












    トップへ












    トップへ












    トップへ












    トップへ












    トップへ












    トップへ












    トップへ












    トップへ












    トップへ












    トップへ












    トップへ












    トップへ












    トップへ












    トップへ












    トップへ












    トップへ












    トップへ












    トップへ












    トップへ












    トップへ












    トップへ












    トップへ












    トップへ












    トップへ












    トップへ












    トップへ












    トップへ












    トップへ












    トップへ