Swiftのタプルと引数･戻り値

　せっかく調べたのでメモ。ただし、その前にクロージャについてメモ。

# クロージャ

　抽象的な文法はこちら。

```
{ (parameters) -> return type in
    statements
}
```

　省略方法は色々。

```
// もっとも長い
{ (m: Int, n: Int) -> Int in
    return m + n
}
```
```
// 引数･戻り値の型を省略
{ m, n in return m + n }
```
```
// returnを省略
{ m, n in m + n }
```
```
// 識別子すら省略
{ $0 + $1 }
```
```
// 何もかも省略、演算子のみ
[1,2,3].reduce(0, +)
```

## クロージャの代入

　基本的には、そのまま代入すればOK (単なる演算子は除く)。

```
let x = { (m: Int, n: Int) -> Int in
    return m + n
}
```

　データ型が推論できない場合でも、引数･戻り値を明示すれば省略を使えます。

```
let x: (Int, Int) -> Int = { $0 + $1 }
```
　個人的には、こういう書き方のほうが分かりやすい気がします。
　ちなみに併用もできます (詳細は後述)。

```
let x: (Int, Int) -> Int = {
    (m: Int, n: Int) -> Int in
    return m + n
}

```

# タプル

　タプルを書くのは括弧で挟むだけ。簡単。

```
let n = (100, 200)
```

　名前付きタプルにするのも名前を書くだけ。簡単。
　使うときには `n.0` でも `n.weight` でも通ります。

```
let n = (weight: 100, height: 200)
```

　**部分的に名前付きタプルにする**のも簡単。

```
let n = (100, height: 200)
```

## 引数としてのタプル

※ よく分からないまま書いています
※※ Playgroundで試しています
※※※ varで宣言すると引数にできません

　「[Swiftにおける名前付き引数](http://qiita.com/south37/items/978eb8adbaff6274aff7)」と「[関数引数としてのタプル](http://blog.skipbit.jp/2014/08/swift-tuple-as-arguments.html)」の2つを突き合わせながら試行錯誤したところ、引数の仕様は次のようになっているようです。

### 関数

　関数の引数は、原則として名前なしのタプルです。

```
func testFunc(hoge: Int, fuga: Int) -> Int {
    return hoge + fuga
}

let n = (1, 2)
testFunc(n)
```

　引数を名前付きにすると、タプルも名前付きにしなければなりません。

```
func testFunc(#hoge: Int, #fuga: Int) -> Int {
    return hoge + fuga
}

let n = (hoge: 1, fuga: 2)
testFunc(n)
```
　部分的に名前付き引数にしても同様です。

```
func testFunc(hoge: Int, #fuga: Int) -> Int {
    return hoge + fuga
}

let n = (1, fuga: 2)
testFunc(n)
```

### クロージャ

　クロージャの引数も、原則として名前なしのタプルです。

```
let testClosure  = {
    (hoge: Int, fuga: Int) -> Int in
    return hoge + fuga
}

let n = (1, 2)
testClosure(n)
```

　しかし、**明示的に「名前付き引数のクロージャ」として宣言すると、名前付きタプルが引数**になります。部分的に名前付き引数にしても同様です。

```
let testClosure: (Int, fuga: Int) -> Int = { $0 + $1 }

let m = (1, fuga: 2)
testClosure(m)
```

　これを利用すると、メンバー関数のような使い方のクロージャも作れます。

```
let addNumber: (Int, with: Int) -> Int = {
    x, y in
    return x + y
}

addNumber(1, with: 2)
```

　書き方が違うだけで、関数の挙動とよく似ています。“[Functions are actually a special case of closures](https://developer.apple.com/library/ios/documentation/Swift/Conceptual/Swift_Programming_Language/GuidedTour.html)” という意味が分かるような気がします。


### メンバー関数

　原則として、「2つ目以降が名前付きになっているタプル」が引数です。
　この例で言えば、`(Int, Int)` ではなく `(Int, fuga: Int)` が引数です。

```
class TestClass {
    func testFunc(hoge: Int, fuga: Int) -> Int {
        return hoge + fuga
    }
}

let test = TestClass()
let n = (1, fuga: 2)
test.testFunc(n)
```

## 戻り値としてのタプル

　Swiftでは、戻り値をタプルにできます。

```
func testFunc() -> (Int, Int) {
    return (10, 20)
}
```

　使い道がピンときませんが、戻り値を名前付きタプルにすることもできます。

```
func testFunc() -> (name: String, age: Int) {
    return ("John", 20)
}
```

# 雑記

　Swiftにおいて、括弧で挟まれた記述はみんなタプルです。たとえばメンバー関数を使うために `test.testFunc(1, fuga: 2)` と書くのは、部分的に名前付きのタプル `(1, fuga: 2)`を引数として渡すのと同じであり、実際そのように書くことができます。
　つまり、**`(Int, Int)` ではなく `(Int, fuga: Int)` という「部分的に名前付きのタプル」がひとつの型・ひとつの引数として処理されている**ようです (たぶん)。

　Swiftにおける引数名の仕様は、外部引数名・ローカル引数名という*ポリシーの問題*ばかりでなく、「名前なしのタプルが引数か、それとも (部分的あるいは全面的に) 名前付きのタプルが引数か」という*引数のデータ型の問題*として捉えてもいいかもしれません。

　なお変数を引数にできない理由は今のところ不明です。