LoginSignup
373
370

More than 5 years have passed since last update.

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

Last updated at Posted at 2014-07-08

概要

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

beta3でArrayの型指定の方法が変わったなーと思って眺めていたら、もっと根本的な変化がありました。
SwiftのArrayがヤバイなどで話題になってたやつです。

公式ドキュメント
The Swift Programming Language

変更点

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 efficient 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コピー実装を使用し、各要素に対し完全で独立したコピーを行います。

古い
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は両方可能という仕様でした。

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

array01[0] = 10

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

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

letとvarの挙動

letはimmutableなので要素の変更も不可
let array = [0, 1, 2]
array[0] = 10 // エラーになる
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]
失敗するlet初期化
let array01 = [0, 1, 2]
let array02 : [Int]?
// これはエラー
array02 = array01
成功する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ではなく、エラーになったようです

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

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

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

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

Dictionaryも変更になっています

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

パフォーマンスについて

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

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

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

まとめ

  • letはimmutableで、要素の変更も不可
  • varはmutableで、要素の変更/追加が可能
  • それ以外にもnilの変更もなんか大きそうな気がする
373
370
10

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
373
370