2014-06-06 47 views
29

如何在Swift中創建一個不可變數組?你如何在Swift中創建一個不可變數組?

的文檔的閱讀淺表會建議你可以做

let myArray = [1,2,3] 

但不幸的是這實際上會產生一個可變的,固定大小的數組。這種可變性創建了沒有料到的混淆和功能變異及其參數通常拼圖:

let outterArray = [myArray, myArray] 
outterArray[0][0] = 2000 
outterArray //=> [[2000,2,3],[2000,2,3]] surprise! 

func notReallyPure(arr:Int[]) ->() { arr[0] = 3000 } 
notReallyPure(myArray) 
myArray // => [3000,2,3] 

比C

如果我想更改的,是最好的選擇也好不到哪去真正把它包起來在NSArray像這樣:

let immutableArray = NSArray(myArray: [1,2,3]) 

這似乎很瘋狂。我在這裏錯過了什麼?

更新(2015年7月26日):

從斯威夫特的最早期這個問題的日期。從那以後,Swift被更新了,因此不可變數組實際上是不可變的,如下面的答案所示。

+1

不幸的是,我想你不會錯過什麼。恕我直言,這是Swift的一個不好的功能。 – Michael

+0

我很確定使用一個元組將保證不變性,但我意識到失去了數組的好處 – Jiaaro

+2

我希望比我理解的更聰明的人比這個更好。這看起來很瘋狂。 – algal

回答

26

這已在Xcode 6的β3.改變雖然陣列中使用爲半可變的,你描述,與它們的元素多變但它們的長度固定的,不可改變現在陣列共享相同的值的語義字典:

從Xcode 6 beta 3發行說明:

•Swift中的數組已經完全重新設計,具有完整的語義,如Dictionary和String在Swift中一直存在。這解決了各種可變性問題 - 現在'let'數組是完全不可變的,'var'數組完全可變 - 與Dictionary和String正確組合,並解決了其他更深層次的問題。如果您習慣使用NSArray或C數組,則數值語義可能會令人驚訝:數組副本現在使用高效的懶惰副本實現生成所有元素的完整獨立副本。這是Array的一個重大變化,仍然有一些性能問題需要解決。請參閱 !請參閱Swift編程語言瞭解更多信息。 (17192555)

2014年7月7日更新了Swift書中有關陣列的原始信息,以反映beta 3的變化。 (如果你在Mac上使用iBooks,像我一樣,你可能需要刪除並重新下載它以獲取7月7日的更新 - 我無法自動更新)

+14

我希望無論誰寫的都會臉紅。 「不變性對數組的意義略有不同」==「然而,對於陣列來說,不變性意味着可變性」 – algal

+1

Xcode 6-beta 3中已經改變了。 – ThomasW

+0

@ThomasW Yup,我會編輯我的答案。 –

1

There這不是一個很好的答案,而且這很奇怪。

但是,您可以通過調用yourArray.unshare()來防止數組在流經程序時發生意外突變。這會導致數組在被分配給新變量時被複制。

+1

有趣。但是你不能只在一個變量上調用常量數組上的'unshare()'! – algal

+0

@algal:是的 - 就像我說的,這很奇怪。常量數組不能共享,但可以修改。所以如果你想防止意外突變,你必須使數組變得可變。 Swift的可變性語義無疑是它最瘋狂的東西。 – Chuck

+1

這是香蕉。據我所知,沒有辦法阻止函數修改數組的內容(或斷言它不能這樣做)。如果函數修改了傳遞給它的「常量」參數類型的數組,則在調用函數之前或之後調用'unshare()'不起作用。你必須相信功能才能做正確的事情。 –

8

似乎是一個錯誤,並很快就會被修復。

Apple dev forum引:

問:

不一致之處讓數組和字典

最終的答案:

這被認爲是一個錯誤,不是一項功能,並將在 中修復後來的Beta。
克里斯

0

恕我直言最簡單的解決方法是簡單地把它包在封閉如下:

let mutableElements = [0,1,2,3] 
let reallyImmutable = {[0,1,2,3]} 
println(mutableElements) 
for i in 0..mutableElements.count { mutableElements[i] *= -1 } 
println(mutableElements) // [0, -1, -2, -3] 
println(reallyImmutable()) 
for i in 0..reallyImmutable().count { reallyImmutable()[i] *= -1 } 
println(reallyImmutable())  // [0, 1, 2, 3] 
println(reallyImmutable()[2]) // 2 
let anotherImmutable = { reallyImmutable().map{ $0 * $0 } } 
println(anotherImmutable())  // [0, 1, 4, 9] 

你付出額外{}的申報和()的每個訪問,但也使您的代碼爲自己說話。

Dan可變編程器

P.S.寫了一個包裝類ImmutableArray

1

現在可以。

Apple Developer

如果分配陣列或字典常數,即陣列或字典是不可變的,其大小和內容不能被改變。

所以現在

let myArray = [1,2,3] 

產生完全不可變陣列。好極了!

相關問題