Apple Swiftのmutabilityの謎

昨晩WWDCの基調講演で発表された、Appleの新しいプログラミング言語Swift。公式ドキュメントを読んで、現時点でいくつか気になったところを書いてみる。

Stringはimmutableなのか

SwiftのString型はimmutableなのかが気になった。JavaC# ではそうだから、Swiftでもそうなのだろうと考えていた。Stringの説明の後半部分にちょうど「String Mutability」という名前の節があったので、以下に引用する。

You indicate whether a particular String can be modified (or mutated) by assigning it to a variable (in which case it can be modified), or to a constant (in which case it cannot be modified):

1 var variableString = "Horse"
2 variableString += " and carriage"
3 // variableString is now "Horse and carriage"
4 
5 let constantString = "Highlander"
6 constantString += " and another Highlander"
7 // this reports a compile-time error - a constant string cannot be modified

(The Swift Programming Language: Strings and Charactersから引用)

つまり、varで束縛したときは変更出来る、letなら出来ないと書いてある。いや、自分が知りたいのはそういうことではない。自分が知りたいのは

var s = "some string"
s[4] = '_'

のようなコードがエラーとなるかどうかなのだ。引用した節はこの例もエラーにならないかのようにも読めるが、サンプルコードはString自身のmutabilityとは関係がなく、確信が持てない。なぜなら

a += b

a = a + b

の略記法であることが述べられており、通常+演算子オペランドのどちらの値も変更しないからだ。実際、引用したコード例ではStringを別の型に置き換えても同様のことがいえるだろう。

もやもやした気持ちを抑えて次の節に目をやった。

Strings Are Value Types

(引用元上に同じ)

値型というのは、オブジェクトをコピーするときに参照のコピーではなく値(中身)のコピーが行われることを指す。これは予想外だった。長大な文字列を扱おうとするときは気を付けるべきだ。同時に、Stringがimmutableであるという予想を怪しいと思い始めた*1。なぜなら、もしimmutableなら値型である必要がない(変更されない保障があるなら参照だけコピーすればよい)からだ。

結局、同章の以降の説明を読んでもStringがmutableかどうかは分からなかった。処理系が手元にあれば早いのだが。

Mutability of Collections

コレクション型の説明をしている章でもmutabilityについての節が存在した。

Arrays and dictionaries store multiple values together in a single collection. If you create an array or a dictionary and assign it to a variable, the collection that is created will be mutable. This means that you can change (or mutate) the size of the collection after it is created by adding more items to the collection, or by removing existing items from the ones it already contains. Conversely, if you assign an array or a dictionary to a constant, that array or dictionary is immutable, and its size cannot be changed.

For dictionaries, immutability also means that you cannot replace the value for an existing key in the dictionary. An immutable dictionary’s contents cannot be changed once they are set.

Immutability has a slightly different meaning for arrays, however. You are still not allowed to perform any action that has the potential to change the size of an immutable array, but you are allowed to set a new value for an existing index in the array. This enables Swift’s Array type to provide optimal performance for array operations when the size of an array is fixed.

(The Swift Programming Language: Collection Types から引用)

varで束縛したときはmutable、letのときはimmutableというところはStringと一緒だ。しかし、Stringのときより少し詳しい説明が入っている。immutableなとき、コレクションのsize(要素数?)を変えることはできない、と。さらに、今あるキーに対する値の更新がimmutableなDictionaryでは出来ないがimmutableなArrayでは出来る、とある。これはどういうことなのだろう。オブジェクトが占有するメモリのサイズを変更できないということなのだろうか。だとすれば、このエラーはコンパイル時ではなく実行時に出るのだろうか。それともメソッドに特別なアノテーションでもつけるのだろうか。

Arrayにはこのほかにも謎の仕様があるようなので、このページのAssignment and Copy Behavior for Arraysという節のコード例には目を通したほうがよさそうだった。Swiftの他にArrayが同じような仕様の言語ってあるのだろうか。筆者は寡聞にして知らない。

Xcode6 beta入れるか迷う。

*1:3日15時頃訂正。元文→「同時に、Stringがmutableなのではないかと思い始めた」