The Swift Programming Language - Function（関数）をまとめる


[The Swift Programming Language をまとめるトップ](http://qiita.com/kiyotaman/items/052f82e9f93590b79c64)

## Function（関数）
デフォルト値の指定ができる
In-Out パラメーター（参照渡し）
ネストもできる


### Defining and Calling Functions（関数の定義と呼び出し）
**func** の後に名前をつけて引数と戻り値を定義する
書式は以下の例を参照

```swift
func 関数名(引数変数: 引数型,,,) -> 戻り値型 {
    return 戻り値型
}
```

**例えば**

```swift
func sayHello(personName: String) -> String {
    let greeting = "ういっす" + personName + "!"
    return greeting
}
println(sayHello("太郎"))
// prints "ういっす太郎!"
println(sayHello("次郎"))
// prints "ういっす次郎!"
````

以下のようにも書ける

```swift
func sayHello(personName: String) -> String {
    return "ういっす" + personName + "!"
}
```

解説は簡単なので省く

### Function Parameters and Return Values（関数の引数と戻り値）
引数と戻り値には何でも指定する事ができ柔軟な仕様になっているとのこと
そりゃそうだろう

### Multiple Input Parameters（複数の引数）
以下のように書く

```swift
func halfOpenRangeLength(start: Int, end: Int) -> Int {
    return end - start
}
println(halfOpenRangeLength(1, 10))
// prints "9"
```

### Functions Without Parameters（引数無し関数）
以下のように書く

```swift
func sayHello() -> String {
    return "こんにちは！"
}
println(sayHello())
// prints "こんにちは！"
```

### Functions Without Return Values（戻り値無し関数）
**->型** を指定しなくてよい

```swift
func sayGoodbye(personName: String) {
    println("さようなら, \(personName)!")
}
sayGoodbye("太郎")
// prints "さようなら, 太郎!"
```

> **NOTE**
> 厳密にいうと **Void型** を返している
> 戻り値を指定して正しく return していない場合、コンパイルエラーとなる

あと、戻り値を指定しても、ただ呼び出しただけの場合、戻り値が無視される

```swift
func printAndCount(stringToPrint: String) -> Int {
    println(stringToPrint)
    return countElements(stringToPrint)
}
func printWithoutCounting(stringToPrint: String) {
    printAndCount(stringToPrint)
}
printAndCount("hello, world")
// prints "hello, world" and returns a value of 12
printWithoutCounting("hello, world")
// prints "hello, world" but does not return a value
```

### Functions with Multiple Return Values（複数の戻り値
複数の戻り値を tuple（タプル）を使って返す事ができる

**例えば**
母音と子音とそれ以外の文字を文字列から数える *count* という関数を定義してみる

```swift
func count(string: String) -> (vowels: Int, consonants: Int, others: Int) {
    var vowels = 0, consonants = 0, others = 0
    for character in string {
        switch String(character).lowercaseString {
        case "a", "e", "i", "o", "u":
            ++vowels
        case "b", "c", "d", "f", "g", "h", "j", "k", "l", "m",
        "n", "p", "q", "r", "s", "t", "v", "w", "x", "y", "z":
            ++consonants
        default:
            ++others
        }
    }
    return (vowels, consonants, others)
}
```

*count*関数をつかって任意の文字列から文字をカウントしてみる

```swift
let total = count("some arbitrary string!")
println("\(total.vowels) 個の母音と \(total.consonants) 個の子音")
// prints "6 個の母音 13 個の子音"
```

既にタプルの値に名前があるので、tuple （タプル）個別の値に名前を指定する必要ない

### Function Parameter Names（関数の引数名）
関数には引数名を必ず付ける

```swift
func someFunction(parameterName: Int) {
    // paremeterName を引数名として、引数の値を参照する
    // このスッコープのみ有効なローカル変数となる
}
```

### External Parameter Names（外面引数名）
引数に名前がつけられる
ローカル変数の前に書く名前が引数名になる
関数を呼び出す時に引数名を指定して値を渡す事ができる
引数の意味が分かりづらいときに使うとよい

```swift
func someFunction(externalParameterName localParameterName: Int) {
    // externalParameterNameで受けてこのスコープ内では localParameterName を引数名として、引数の値を参照する
}
```

**例えば**

```swift
func join(string s1: String, toString s2: String, withJoiner joiner: String)
    -> String {
        return s1 + joiner + s2
}

join(string: "hello", toString: "world", withJoiner: ", ")
// returns "hello, world"

```

### Shorthand External Parameter Names（簡単な外部引数名）
引数に名前をつける時に以下の様に（#）を使うことが出来る

**例えば**

```swift
func containsCharacter(#string: String, #characterToFind: Character) -> Bool {
    for character in string {
        if character == characterToFind {
            return true
        }
    }
    return false
}
let containsAVee = containsCharacter(string: "aardvark", characterToFind: "v")
// containsAVee は true, 理由は "aardvark" は "v" を含むので

```

### Default Parameter Values（引数初期値指定）
引数の初期値が指定されていたら、関数を呼び出す時にその引数を省略することができる

> **NOTE**
> 初期値を指定した引数は分かりやすくする為に引数の最後に指定することが望ましい

**例えば**

joiner に初期値 " " を指定

```swift
func join(string s1: String, toString s2: String,
    withJoiner joiner: String = " ") -> String {
        return s1 + joiner + s2
}

// 省略して呼び出す事ができる
join(string: "hello", toString: "world")
// returns "hello world"
```

### External Names for Parameters with Default Values（初期値の外部引数について）
Swift では引数に初期値をしていた場合、自動的に外部引数名が割り当てられる
以下の例だと、joiner を明示的に引数名として指定する事ができる

**例えば**

```swift
func join(s1: String, s2: String, joiner: String = " ") -> String {
    return s1 + joiner + s2
}

// (#)の指定が無くても、joiner を外部引数名として指定する事ができる
join("hello", "world", joiner: "-")
```

### Variadic Parameters（可変引数）
ゼロ個または一つ以上の引数を指定する時に使う
(...) を引数の型名の後に続ける

```swift
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)
// returns 3.0
```

> **NOTE**
> 可変引数を使う時は、初期値指定のある引数より後、つまり、一番最後に指定する

### Constant and Variable Parameters（定数と変数引数）
関数の引数はデフォルトは定数
仮に引数の値を変更しようとした場合、コンパイルエラーになる
引数を変更したい場合、変数に再定義する必要がある
**var** を最初に指定して初期化して複製をつくる

```swift
func alignRight(var string: String, count: Int, pad: Character) -> String {
    let amountToPad = count - countElements(string)
    for _ in 1...amountToPad {
        string = pad + string
    }
    return string
}
let originalString = "hello"
let paddedString = alignRight(originalString, 10, "-")
// paddedString は "-----hello"
// originalString は "hello" のまま
```

### In-Out Parameters（In-Out引数、参照渡し）
**inout** を引数の前にしていすると、参照渡しになる
関数内での変更が関数へ渡されたオリジナルの値にも変更が加わる
**inout** を使う時は引数に渡される値は **var** で定義された変数になる
値を渡す時は（&）を使う

**例えば**

```swift
// inout を指定する
func swapTwoInts(inout a: Int, inout b: Int) {
    let temporaryA = a
    a = b
    b = temporaryA
}

var someInt = 3
var anotherInt = 107

// （&）を付ける
swapTwoInts(&someInt, &anotherInt)
println("someInt は \(someInt), そして anotherInt は \(anotherInt) になる")
// prints "someInt は 107, そして anotherInt は 3 になる"
```

### Function Types（関数型）
どんな関数でも型を必ずもっている
型を明示的に指定しない場合、**Void** を返す
**Void** は () 空のタプルと同じ

### Using Function Types（関数型の利用）
関数自体にも型指定ができる
定数と変数を定義できる

```swift
func addTwoInts(a: Int, b: Int) -> Int {
    return a + b
}

func multiplyTwoInts(a: Int, b: Int) -> Int {
    return a * b
}

var mathFunction: (Int, Int) -> Int = addTwoInts
println("結果: \(mathFunction(2, 3))")
println("Result: \(mathFunction(2, 3))")

// var変数なので、別の関すを代入
mathFunction = multiplyTwoInts
println("結果: \(mathFunction(2, 3))")
// prints "結果: 6"

// 以下の用に定義を書かなくても、推論してくれる
let anotherMathFunction = addTwoInts
```

### Function Types as Parameter Types（関数型を引数に）
関数型を引数として使う事ができる

**例えば**

```swift
func printMathResult(mathFunction: (Int, Int) -> Int, a: Int, b: Int) {
    println("Result: \(mathFunction(a, b))")
}
printMathResult(addTwoInts, 3, 5)
// prints "結果: 8"
```

### Function Types as Return Types（関数型を戻り値に）
戻り値に関数型を指定する事ができる

**例えば**

```swift
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)
// currentValue > 0 は true なので、stepBackward()関数 を返す
// よって、moveNearerToZero は stepBackward() を参照する

println("ゼロまでカウント開始")
// Counting to zero:
while currentValue != 0 {
    println("\(currentValue)... ")
    // stepBackword()が呼ばれるので、上記 currentValue - 1 される
    currentValue = moveNearerToZero(currentValue)
}
println("zero!")
// 3...
// 2...
// 1...
// zero!
```

### Nested Functions（関数のネスト）
局所的に関数を使いたい場合にネストが使える

**例えば**
chooseStepFunction を書き換えてみる

```swift
func chooseStepFunction(backwards: Bool) -> (Int) -> Int {
    func stepForward(input: Int) -> Int { return input + 1 }
    func stepBackward(input: Int) -> Int { return input - 1 }
    return backwards ? stepBackward : stepForward
}
var currentValue = -4
let moveNearerToZero = chooseStepFunction(currentValue > 0)
// chooseStepFunctionの引数の値はは currentValue > 0 で false なになる
// backwards に false が代入される
// 三項演算子 "?" を使ってその backwards を評価し、
// それが false なので、":" の右の stepForward()関数 を返す
// よって、moveNearerToZero は stepForward() を参照することになる
while currentValue != 0 {
    println("\(currentValue)... ")
    currentValue = moveNearerToZero(currentValue)
}
println("zero!")
// -4...
// -3...
// -2...
// -1...
// zero!