Swift 隐式展开的可选项使其不可变

Swift 隐式展开的可选项使其不可变,swift,Swift,为什么我不能改变隐式展开的可选变量 下面是一个简短的示例,该示例再现了该问题: 带数组 类型“[Int]”的不可变值只有名为“append”的变异成员。 带Int 找不到接受提供的参数的“+=”的重载,因为您尝试对它们进行变异的方式是通过变异值(不可变)而不是变异变量 在Swift中,值类型是不可变的。永远都是 突变不是值的突变,而是包含值的变量的突变 在Int的情况下,+=操作符在左侧获得一个结构,在右侧获得一个Int,并且它不能向Int添加结构 在数组的情况下,追加是一个变异成员。但它是在不

为什么我不能改变隐式展开的可选变量

下面是一个简短的示例,该示例再现了该问题:

带数组
类型“[Int]”的不可变值只有名为“append”的变异成员。

带Int
找不到接受提供的参数的“+=”的重载,因为您尝试对它们进行变异的方式是通过变异值(不可变)而不是变异
变量

在Swift中,值类型是不可变的。永远都是

突变不是值的突变,而是包含值的变量的突变

Int
的情况下,
+=
操作符在左侧获得一个结构,在右侧获得一个Int,并且它不能向Int添加结构


数组
的情况下,
追加
是一个变异成员。但它是在不直接存储在变量中的不可变值上调用的。它只能对直接存储在变量中的值进行操作(这就是使它们可变的原因:它们存储在变量中。它们不是真正可变的,变量才是)。

更新:

这已在Xcode Beta 5中修复,但有一点需要注意:

var list: [Int]! = [1]
list.append(10)

var number: Int! = 1
number! += 2
number += 2 // compile error
数组按预期工作,但似乎现在整数仍然需要显式展开才能使用
+=



目前,这正是Optionals的本质(无论是否隐式展开)。“展开”操作符返回一个不可变的值

目前唯一的解决方法是将数组包装到类中:

class IntArray {
    var elements : [Int]
}

错。在Swift中,赋值给变量时,默认情况下,值类型(如
String
)和集合类型(如
Int[]
)是可变的。只有当您将它们赋给常数(即
let
)时,它们才成为不可变的。请转到。可变的是变量,而不是值。对于值类型,值始终是不可变的。文档有时以非正式的方式表达,有时则更正式。当它说字符串或数组在分配给
var
时是可变的,而在分配给
let
时是不可变的时,它只是说值本身是不可变的,但您可以将其分配给可变的
var
并对该var进行变异。这就是为什么您不能调用任何仅是另一类型构造函数参数的变异方法。
“如果您创建数组或字典并将其分配给变量,则创建的集合将是可变的。”
我看不出这有什么不清楚的地方。不清楚。这并不意味着你认为这意味着什么。这意味着您可以调用该值的变异方法。变异方法所做的是,它们获取一个隐藏的参数,即变量的地址,创建一个新值,并将其分配给变量。它们不会改变实际的原始值(除非编译器能够证明没有别名或共享,在这种情况下,它可以执行优化并实际改变原始存储,但这是透明的),数组的变异意味着长度的变异,而不是内容的变异。事实上,这就是为什么OP中的
append
调用失败的原因:它是数组的一种变异方法。它需要创建一个新数组并将其分配给一个变量,但只有当它有一个变量,并且没有包含该数组的变量时,它才能这样做。展开运算符返回一个不可变值,因为这是不可变操作的本质。正如拉特纳所说,没有明显的解决办法。使展开操作可变并不是一个解决方案:您将无法在不可变的
可选
上使用它,而且它也无法解决问题,因为返回的值仍然是不可变的(因为所有值类型始终是不可变的)。
var list: [Int]! = [1]
list.append(10)

var number: Int! = 1
number! += 2
number += 2 // compile error
class IntArray {
    var elements : [Int]
}