
今でしょ!Swift - 関数の関数型
関数型
全ての関数には特定の関数型があり、パラメータの型と戻り値の型で構成されています。
func addTwoInts(_ a: Int, _ b: Int) -> Int {
return a + b
}
func multiplyTwoInts(_ a: Int, _ b: Int) -> Int {
return a * b
}
この例では、addTwoInts および multiplyTwoInts と呼ばれる 2 つのシンプルな数学関数を定義します。これらの関数はそれぞれ 2 つの Int 値を取り、適切な数学演算を実行した結果の Int 値を返します。
これらの関数の両方の型は、(Int, Int) -> Int です。これは次のように読むことができます:
「両方とも Int 型の 2 つの値を受け取り、Int 型の値を返す関数です」
パラメータや戻り値のない関数
func printHelloWorld() {
print("hello, world")
}
関数の型は、() -> Void
関数型の使用
定数または変数を関数型として定義し、その変数に適切な関数を代入することができます:
var mathFunction: (Int, Int) -> Int = addTwoInts
代入した関数を mathFunction という名前で呼び出すことができます。
mathFunction = multiplyTwoInts
print("結果: \(mathFunction(2, 3))")
// 結果: 6
他の型と同様に、定数または変数に関数を代入するときに、関数型を推論することができます
let anotherMathFunction = addTwoInts
// anotherMathFunction は (Int, Int) -> Int と推論されます
パラメータの型としての関数型
引数に別に定義した関数を使うことができます。引数で関数を使うことで大元の関数に違う機能を持たせることができます。
func printMathResult(_ mathFunction: (Int, Int) -> Int, _ a: Int, _ b: Int) {
print("結果: \(mathFunction(a, b))")
}
printMathResult(addTwoInts, 3, 5)
// 結果: 8
この例ではaddTwoIntsという足し算をする関数を引数で使うことによって、同時に入力された2つの引数の数字を使って足し算を行わせています。
戻り値の型としての関数型
まずシンプルな関数を定義します。
func stepForward(_ input: Int) -> Int {
return input + 1
}
func stepBackward(_ input: Int) -> Int {
return input - 1
}
先に定義した関数を戻り値として使います。この場合backwardが真であれば stepBackwardが実行されます。
func chooseStepFunction(backward: Bool) -> (Int) -> Int {
return backward ? stepBackward : stepForward
ここで定義したchooseStepFunctionを変数moveNearerToZeroに代入しておきます。
var currentValue = 3
let moveNearerToZero = chooseStepFunction(backward: currentValue > 0)
// moveNearerToZero は stepBackward() 関数を参照しています
変数moveNearerToZeroを使って以下コードを実行します。currentValueが今"3"なので判定は真となり stepBackwardが実行されカウントダウンが実行されます。
print("0 までカウントします:")
// 0 までカウントします:
while currentValue != 0 {
print("\(currentValue)... ")
currentValue = moveNearerToZero(currentValue)
}
print("0!")
// 3...
// 2...
// 1...
// 0!
ネスト関数
関数の中に関数を入れ込むネスト関数として書き直してあります。
func chooseStepFunction(backward: Bool) -> (Int) -> Int {
func stepForward(input: Int) -> Int { return input + 1 }
func stepBackward(input: Int) -> Int { return input - 1 }
return backward ? stepBackward : stepForward
}
var currentValue = -4
let moveNearerToZero = chooseStepFunction(backward: currentValue > 0)
// moveNearerToZero は ネスト関数の stepForward() を参照しています
while currentValue != 0 {
print("\(currentValue)... ")
currentValue = moveNearerToZero(currentValue)
}
print("0!")
// -4...
// -3...
// -2...
// -1...
// 0!