Swift言語:関数

概要

swiftの関数について仕様を確認しました。The Swift Programming Language (Swift 2.1) - Functions

引数なし

func hello() {
    print("hello World")
}

hello()

引き数あり

外部引き数名なし

第2引数は引き数名を付けないとコンパイルエラーになる

func calcTriangle(w: Float, h: Float) -> Float {
    return (w * h * 0.5)
    
}
calcTriangle(10.0, 20.0) --> コンパイルエラー
calcTriangle(10.0, h: 20.0)

引き数名を明示的に省略することもできる。

入力を間違えやすくなるので使う場所を考える必要がある。

func calcTriangle2(w: Float, _ h: Float) -> Float {
    return (w * h * 0.5)
    
}
calcTriangle2(10.0, 20.0)

外部引き数名あり

外部引き数名を使った方がわかりやすい例

内部引き数名を省略形にすることはあるが、関数を呼び出す時には分かりやすい名前を指定する。

先頭の引数は省略可能だが、省略しない方がベター。

func calcTriangle3(base w: Float, height h: Float) -> Float {
    return (w * h * 0.5)
    
}
calcTriangle3(base: 10.0, height: 20.0)

引数を省略してもわかりやすい例

自然言語的に意味のある文になっている(say Hello To Tom)

関数名は、自然言語として読みやすい名前をつけるようにする(by Readable Code)

func sayHello(name: String) {
    print("Hello! " + name)
}

sayHello("Tom")

外部引数名が不要なケース

関数swap。1番目の引数と2番目の引数で値を入れ替えるので名前は意味を持たない。

func doSwap(inout a: Int, inout _ b: Int) {
    let tmp = a
    a = b
    b = tmp
}
var a = 10
var b = 100
swap(&a, &b)
print("a = \(a), b = \(b)")

デフォルト引数値

引数の値を省略するとデフォルト値が適用される。

func someFunction(parameterWithDefault: Int = 12) {
    // function body goes here
    // if no arguments are passed to the function call,
    // value of parameterWithDefault is 12
}
someFunction(6) // parameterWithDefault is 6
someFunction() // parameterWithDefault is 12

可変長引数

可変長引数にすると、引数の長さを不定にできる。

func arithmeticMean(numbers: Double...) -> Double {
    var total: Double = 0
    for number in numbers {
        total += number
    }
    return total / Double(numbers.count)
}
arithmeticMean(1, 2, 3, 4, 5)

返値あり

単一返値

-> 型という書式で返値を宣言できる。

func min(array: [Int]) -> Int {
    var min = array[0]
    for n in array {
        if n < min {
            min = n
        }
    }
    return min
}
let minOfArray = min([1, -2, 3, 10, 5])
print("min = \(minOfArray)")

返値は、Optional型にすることもできる。

func minEx(array: [Int]) -> Int? {
    if array.isEmpty { return nil }
    
    var min = array[0]
    for n in array {
        if n < min {
            min = n
        }
    }
    return min
}

let minValue = minEx([1, -2, 3, 10, 5])
if let min = minValue {
    print("min = \(min)")
}

複数返値

返値をタプルで宣言すると複数の値を返値にすることができる。

返値にも名前を付けることができる。

返値の値は、index(0,1,...)あるいは、名前(min, max)で取得できる。

func minMax(array: [Int]) -> (min: Int, max: Int) {
    var currentMin = array[0]
    var currentMax = array[0]
    for value in array[1.. currentMax {
            currentMax = value
        }
    }
    return (currentMin, currentMax)
}
let bounds = minMax([8, -6, 2, 109, 3, 71])
print("min is \(bounds.min) and max is \(bounds.max)")

クロージャー

クロージャーの場合には、引数をタプルで渡すこともできる。

let f4: (String, Int) -> (Int, String) = { args in
    let (a, b) = args
    return (b, a)
}

let tuple = ("aaa", 1)
f4(tuple)

ただし、引数に名前が付いている場合はダメみたい。

func test(a: String, b: Int) -> (Int, String) {
    return (b, a)
}
// Missing argument for parameter 'b' in call
// test(tuple)

関数の引数・返値が関数の場合

関数の引数・返値に関数が使える。

引数の場合

func addTwoInts(x: Int, y: Int) -> Int {
	return (x + y)
}
func printMathResult(mathFunction: (Int, Int) -> Int, _ a: Int, _ b: Int) {
    print("Result: \(mathFunction(a, b))")
}
printMathResult(addTwoInts, 3, 5)
// prints "Result: 8"

返値の場合

func stepForward(input: Int) -> Int {
    return input + 1
}
func stepBackward(input: Int) -> Int {
    return input - 1
}
func chooseStepFunction(backwards: Bool) -> (Int) -> Int {
    return backwards ? stepBackward : stepForward
}
var currentValue = 3
let moveNearerToZero = chooseStepFunction(currentValue > 0)
print("Counting to zero:")
// Counting to zero:
while currentValue != 0 {
    print("\(currentValue)... ")
    currentValue = moveNearerToZero(currentValue)
}
print("zero!")
// 3...
// 2...
// 1...
// zero!

関連資料