SwiftのArrayがヤバくなくなった


# 概要

**思ったよりバズったので、いくつか加筆修正しました**

beta3でArrayの型指定の方法が変わったなーと思って眺めていたら、もっと根本的な変化がありました。
[SwiftのArrayがヤバイ](http://qiita.com/koher/items/6f54eafac59793e7c364)などで話題になってたやつです。

公式ドキュメント
[The Swift Programming Language](https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/CollectionTypes.html#//apple_ref/doc/uid/TP40014097-CH8-XID_133)

変更点

>Array in Swift has been completely redesigned to have full value semantics like Dictionary and String have always had in Swift.  This resolves various mutability problems – now a 'let' array is completely immutable, and a 'var' array is completely mutable – composes properly with Dictionary and String, and solves other deeper problems.  Value semantics may be surprising if you are used to NSArray or C arrays: a copy of the array now produces a full and independent copy of all of the elements using an efﬁcient lazy copy implementation.  This is a major change for Array, and there are still some performance issues to be addressed.  Please see the Swift Programming Language for more information.

arrayはDictionaryと同じ挙動をするように再設計されました。
これにより、様々な問題が解決されます。
let arrayは完全にimmutableに、var arrayは完全にmutableになりました。
arrayのコピーは、効率的なlazyコピー実装を使用し、各要素に対し完全で独立したコピーを行います。

```swift:古い
var array01 = [0, 1, 2]
var array02 = array01 // [0, 1, 2]

array01[0] = 10

// 両方共同じ
// array01 => [10, 1, 2]
// array02 => [10, 1, 2]

array01.append(3)

// 追加すると参照でなくなる
// array01 => [10, 1, 2, 3]
// array02 => [10, 1, 2]
```

以前は要素の変更は参照のまま、appendすると参照切れてコピーになるという挙動でした。
また、letは要素の変更は可能、appendは不可。varは両方可能という仕様でした。

```swift:新しい
var array01 = [0, 1, 2]
var array02 = array01

array01[0] = 10

// 参照でなくコピーになってる
// array01 => [10, 1, 2]
// array02 => [0, 1, 2]
```

今回の変更で、letは要素の変更も追加も不可。varは両方可能。
また、varは必ず参照ではなくコピーになるようになりました。
シンプル。

# letとvarの挙動

```swift:letはimmutableなので要素の変更も不可
let array = [0, 1, 2]
array[0] = 10 // エラーになる
```

```swift:letをvarへコピー
let array01 = [0, 1, 2]
var array02 = array01

// array01からarray02へコピーされた。
// array01 => [0, 1, 2]
// array02 => [0, 1, 2]

// array02はmutableなので要素の変更/追加が可能
array02[0] = 10
array02.append(3)

// array01 => [0, 1, 2]
// array02 => [10, 1, 2, 3]
```

```swift:失敗するlet初期化
let array01 = [0, 1, 2]
let array02 : [Int]?
// これはエラー
array02 = array01
```

```swift:成功するlet初期化
var array01 = [0, 1, 2]
let array02 : [Int] = array01

array01[0] = 100

// array01 => [100, 1, 2]
// array02 => [0, 1, 2]
```

# 型の指定方法も変更

http://qiita.com/aki/items/7544b155045361b4bdc5
こっちにも書きましたが、一応転載

先ほどXcode6beta3を入れてswiftのプロジェクトを開いたところ、Warningが増えていた。

**Array types are now written with the brackets around the element type**

これまでの配列の型の指定の書き方が、非推奨になって新しい書き方に変わるらしい。
エラーではないので、どちらでも動作上は問題ありません。

**2014/7/22追記**
beta4ではWarningではなく、エラーになったようです

```swift:Arrayの型指定
//Xcode6beta2以前
let arrayOld : Int[] = [10, 20, 30]

//Xcode6beta3以降
let arrayNew : [Int] = [10, 20, 30]
```

こんな感じで、型の後ろに[]ではなくて、[型]と囲むようになりました。
新しい書き方のほうが直感的でいいですね。

※反応を見ていると、前のほうがいいという声も多いようです。
※今まで静的型付言語をやったことがほとんどなかったので、なんか勘違いしてるのかもしれません。

## Dictionaryも変更になっています

```swift:
// こちらはWarningは出ないので、非推奨ではなさそう
var dictionary01: Dictionary<String, NSObject?> = ["key1": "A", "key2": "B"]
// 新しい書き方、と言うよりは上のシンタックスシュガーぽい
var dictionary02:[String: NSObject?] = ["key1": "A", "key2": "B"]
```

# パフォーマンスについて

そもそも前の仕様になっていた理由として考えられていたのが、パフォーマンスのためだろうという話がありました。
で、変わったということはパフォーマンスが落ちたのではないかという危惧もあるわけです。

リリースノートにも、解決すべきパフォーマンス上の問題が残っていることが記載されています。
解決すべきとなっているので、おそらくリリースまでには改良されるんじゃないかと思います。

また、ちょっと正確にはわからなかったのですが、「効率的なlazyコピー」を行っているとなっているのでコピーの場合でもメモリとかパフォーマンスが出るような設計になってるのではないかなと。

# まとめ
- letはimmutableで、要素の変更も不可
- varはmutableで、要素の変更/追加が可能
- それ以外にもnilの変更もなんか大きそうな気がする