2014-06-06 48 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] 

产生完全不可变阵列。好极了!

相关问题