ArrayとOptionalのmapは同じです

> Optional型にも map() メソッドがあるのですね。
> mapがどういう存在なのか、ますます分からなくなってきました。

[Swiftの全関数一覧](http://qiita.com/tottokotkd/items/8a014145a337ee10ba8e)で @tottokotkd さんからこのような返信をいただいたので、 __`Array` と `Optional` の `map` メソッド／関数は概念として同じものだ__ という内容のコメントを書きました。他にも同様の疑問を持っている人がいるかもしれないと思い、本投稿は上記投稿へのコメントを加筆・修正して、独立した記事として投稿したものです。

mapとは何か
---------------------------------

`Optional` や `Array` を値を入れる箱だと考えると、 __`map` は箱から値を取り出さずに操作するためのメソッド／関数です__（正確には、操作した結果を新しい箱に格納して返します）。

### Optionalの場合

例えば、

```swift
let a: Optional<Int> = 3 // Optional<Int> は Int? と等価
```

があったとして、箱 `Optional` の中身 `Int` を二乗したい場合は次のようにできます。

```swift
let b: Optional<Int> = a.map { $0 * $0 } // Optional(9)
```

`a` が `nil` のときは結果も `nil` になります。

```swift
let a: Optional<Int> = nil
let b: Optional<Int> = a.map { $0 * $0 } // nil
```

もし中身を取り出してこれをやろうとすると次のようになり非常に面倒です（しかも `let` でなくなってしまいました…）。

```swift
let a: Optional<Int> = 3
var b: Optional<Int>
if let a0 = a {
    b = a0 * a0
} else {
    b = nil
}
```

### Arrayの場合

`Array` の `map` も同様です。次のコードは箱 `Array` の中身 `Int` を箱から取り出さずに二乗します。

```swift
let a: Array<Int> = [2, 3, 5] // Array<Int> は [Int] と等価
let b: Array<Int> = a.map { $0 * $0 } // [4, 9, 25]
```

ArrayとOptionalの関係
---------------------------------

`Optional` は最大で一つしか要素を入れられない `Array` と考えることができます。上記の `Optional` のコードを `Array` で表すと次のようになります。

```swift
let a: Array<Int> = [3] // Optional(3) 相当
let b: Array<Int> = a.map { $0 * $0 } // [9]
```

```swift
let a: Array<Int> = [] // nil 相当
let b: Array<Int> = a.map { $0 * $0 } // []
```

このように、 __`Array` と `Optional` を対応させて考えることができ、それらの `map` は同じ概念を表しています__。

（おまけ）より高度な抽象化とflatMap
---------------------------------

`Array` と `Optional` は共に _ファンクター_ や _モナド_ であり、より高度な抽象化ができます（ `map` は _ファンクター_ と関係があります。そのうち詳しい説明を書くかもしれません）。 → ["モナドについてSwiftで説明してみた"](http://qiita.com/koher/items/12f72f2fc2db7fa709cf)

特に _モナド_ の持つ `flatMap` や `bind` などと呼ばれるメソッド／関数はとても便利です。 `flatMap` は _Optional Chaining_ と似ていますが、 _Optional Chaining_ でできないこともできます。

```swift:ArrayのflatMap
// 要素の数だけ要素を繰り返した Array を作る
[1, 2, 3].flatMap { [Int](count: $0, repeatedValue: $0) } // [1, 2, 2, 3, 3, 3]
```

```swift:OptionalのflatMap
// Optional な値同士を計算する
let a: Optional<Int> = 2
let b: Optional<Int> = 3
a.flatMap { a0 in b.flatMap { b0 in a0 + b0 } } // Optional(5)
```

### mapとflatMapの関係

上記のコードの `flatMap` を `map` に置き換えてみるとどうなるでしょうか。

```swift:Array
[1, 2, 3].map { [Int](count: $0, repeatedValue: $0) } // [[1], [2, 2], [3, 3, 3]]
```

```swift:Optional
let a: Optional<Int> = 2
let b: Optional<Int> = 3
a.map { a0 in b.map { b0 in a0 + b0 } } // Optional(Optional(5))
```

前者の戻り値の型は `Array<Array<Int>>` 、後者の戻り値の型は `Optional<Optional<Int>>` です。二重に箱に入ってしまいました。 `flatMap` はこの二重の箱を flat に（一重に）してくれるから `flatMap` なのです。

`flatMap` の型は次の通りです。

```swift
extension Array {
	func flatMap<U>(transform: T -> [U]) -> [U]
}

extension Optional {
	func flatMap<U>(transform: T -> U?) -> U?
}
```

### ArrayとOptionalを混ぜて使う

`Array` と `Optional` を混ぜて使うための `flatMap` が Swift 2.0 で追加されました。 → ["Swift 2.0の新しいflatMapが便利過ぎる"](http://qiita.com/koher/items/6a95cb8edb04fb81f787)

### flatMapの入れ子の代わりにアプリカティブ

さらに余談ですが、 `Optional` の `flatMap` の例でやった `Optional` な値同士の計算は、[前に書いたようにアプリカティブを使う方法](http://qiita.com/koher/items/95583f58a443f6a33c28)もあります。

```swift
let a: Int? = 2
let b: Int? = 3
(+) <%> a <*> b // Optional(5)
```