iOS 8 Beta 3 中的Swift Arrays

发布于:2014-07-21 15:41阅读数:

或许在Beta 3发布后不久我就该写这篇文章了,不过我发现我此前写的与Swift数组语义相关的文章还有一些流量。我非常乐意看到Beta 3中Swift数组的新变化,有了完整的值语义。声明数组的语法也

 
或许在Beta 3发布后不久我就该写这篇文章了,不过我发现我此前写的与Swift 数组 array semantics 相关的文章还有一些流量。我非常乐意看到Beta 3中Swift数组的新变化,有了完整的值语义。声明数组的语法也有改变,尽管旧语法也没有什么特别的问题。记得更新Swift iBooks(删除再重装)来了解一些重要的改变
 
Beta 3中删除了 copy() unshare() 两个函数,因为unshare已经成为默认操作。
 
语义变化
1. 数组不再是引用类型。你可以像对待副本一样对待每个分配、参数传递和函数返回。
2. 当使用let将数组声明为常量时,就不允许改变数组的元素。
 
如下例,CoW(copy-on-write)操作使用恒等操作符“===”(在实际编码中我不建议在CoW状态使用这种操作,但是这个操作可以帮我们观察CoW)。在这个例子中,使用let或者var声明a是没有区别的,但是只能使用var声明b,否则由于元素的改变,将会出现编译时错误。
  1. var a = [1,2,3] 
  2. var b = a 
  3. a == b        // true 
  4. a === b       // true 
  5. b[0] = 10 
  6. a             // [1,2,3] 
  7. b             // [10,2,3] 
  8. b[0] = 1 
  9. a == b        // true 
  10. a === b       // false 
  11. a             // [1,2,3] 
  12. b             // [1,2,3] 
注意:如果数组包含类的对象,那么即便使用let声明数组,也可完全访问或者修改对象。但不可以改变或者重新排序数组中的对象。
 
在结构体中,当使用let声明数组时,尽管字典和其他类型值可以赋值给一个变量,但也不能修改它们。如下代码,如果使用let而不是var来声明e,就会出现编译错误: 
  1. var e = [["a":1]] 
  2. e[0]["a"] = 5 
语法变化
Beta 3中,显式声明数组(和字典)类型的语法已经改变了。
  1. // Note in Swift you usually don't have to state the type it can be inferred but it is useful to be able to do so if you are assigning an empty collection. It can also be necessary in function declarations. 
  2.   
  3. // Beta 1 and 2 
  4. var c:Int[] = [] 
  5. // No way of specifiying type really just create the instance of the generic and let type inference define the type of d. 
  6. var d = Dictionary<Int:String>() 
  7.   
  8.   
  9. // Beta 3 
  10. var c:[Int] = [] 
  11. var d:[Int:String] = [:] 
数组实际上没有太大的不同,但是它清理了很多字典类型的语法,并且与其保持了一致性,这确实是个正向的改变。
 
 其他观点
不是所有人(Design issues in Swift language’s arrays)都喜欢新的数组功能,HackerNews有篇文章此观点进行了讨论,问题如下:
现在混叠一个数组将会复制数组,这不是很奇怪么?
 
接下来的讨论围绕苹果所提到的CoW,这个概念的描述和声明实际上将一个数组赋值给另一个数组的过程描述为“aliasing”。依我所见,对这种操作的看法完全是错误的。这种操作是赋值过程中的值类型拷贝。除非你深究恒等运算符(===),或者处理大型数组和监控执行,否则你永远都不会知道这个操作确实是CoW。所以,几乎所有[0]这些副本在不改变语义的情况下得到了优化。
 
在我看来,其余的观点都是基于Swift中值类型(数组、字典、结构体、字符串和基本类型)赋值的错误概念。
 
[0]Copy on Write将避免每次传递数组时的副本,但在调用函数OR过程中不要再次使用它。在被调用者中它不会修改。每次你返回的数组是本地OR,它是一个不会在返回结果被释放前改变的属性。当然你编写代码会产生很多副本,但通常好的结构化代码不会这样做。.
 
[1]我已经从Google缓存中保存了这篇文章,因为我不确定Google缓存链接将保留多久。其目的是为了不歪曲本文中所阐述的论点。

CocoaChina是全球最大的苹果开发中文社区,官方微信每日定时推送各种精彩的研发教程资源和工具,介绍app推广营销经验,最新企业招聘和外包信息,以及Cocos2d引擎、Cocos Studio开发工具包的最新动态及培训信息。关注微信可以第一时间了解最新产品和服务动态,微信在手,天下我有!

请搜索微信号“CocoaChina”关注我们!

搜索CocoaChina微信公众号:CocoaChina

顶部