Swift's array

在 stack overflow 上有著一個有關 Swift 的問題:

Is there a reason that Swift array assignment is inconsistent (neither a reference nor a deep copy)?

這位仁兄發現 Array 的行為非常奇怪,以下是他的說明:

範例 1:

var a = [1, 2, 3]
var b = a
a[1] = 42
// a is [1, 42, 3]
// b is [1, 42, 3]

以上 ab 的值都一樣,很合理,因為 var b = a


範例 2:

var c = [1, 2, 3]
var d = c
c.append(42)
// c is [1, 2, 3, 42]
// d is [1, 2, 3]

cd 竟然不一樣,依照「範例 1」來推論,d 應該要是 [1, 2, 3, 42] 呀?


var e = [1, 2, 3]
var f = e
e[0..2] = [4, 5]
// e is [4, 5, 3]
// f is [1, 2, 3]

ef 竟然也不一樣,依照「範例 1」來推論,f 應該要是 [4, 5, 3] 呀?

到底怎麼了?這是 bug 嘛?


其中有一位 Lukas 出來說明,是目前最多人贊同的答案,他說中有一段話提到:

For arrays, copying only takes place when you perform an action that has the potential to modify the length of the array. This includes appending, inserting, or removing items, or using a ranged subscript to replace a range of items in the array.

大綱是說:任何會修改到 array 長度的操作(像是 append, insert, remove, replace等),會因為 performance 的關係,而直接 copying 一個新的 array 做操作,並且回傳這個新的 array。

由此可知,「範例 2」跟「範例 3」因為是符合上述條件(append, range replacing),因此直接回傳一個新的 array,因此 df 的值才會不同。

小結

這種不一致的行為真的會讓人搞混,有人說是 bug,也有人說是語言特性,不過我想 Swift 才剛出來,這種神奇的行為應該是可以再做修改的。