Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/swift/16.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Swift 不可变的'var'数组_Swift_Immutability - Fatal编程技术网

Swift 不可变的'var'数组

Swift 不可变的'var'数组,swift,immutability,Swift,Immutability,我想用Swift创建一个数组,它是不可变的,但可以完全替换,采用函数式编程的风格 我知道我可以通过以下方式创建它们: var mutable = [1,2,3] // can change reference, add, remove, etc let immutable = [4,5,6] // cannot replace reference or add, remove, etc 我想要不可变的属性,但仍然能够更改变量指向的不可变数组。例如,我希望此操作失败: myArr.appen

我想用Swift创建一个数组,它是不可变的,但可以完全替换,采用函数式编程的风格

我知道我可以通过以下方式创建它们:

var mutable   = [1,2,3] // can change reference, add, remove, etc
let immutable = [4,5,6] // cannot replace reference or add, remove, etc
我想要不可变的属性,但仍然能够更改变量指向的不可变数组。例如,我希望此操作失败:

myArr.append(42) // fails. immutable array
但我希望这一切能够成功:

// Desired behavior:
// Multiply each element in the immutable array by 2
// Return a new immutable array, assigned to the old var
immutable = immutable.map { $0 * 2 } // ERROR: can't replace immutable ref
类似,但不是答案:


在这种情况下,
let
不能使用,因为它在整个运行时都不会更改

我个人更喜欢使用
var
并声明
NSArray
。您可以重新分配变量以指向另一个不可变的
NSArray
,但不能修改
NSArray
的内容


陷阱在于,如果您设法将其强制转换为
NSMutableArray

我不知道如何使用内置的
数组
类型来实现这一点,则会产生运行时崩溃。 您可以做的是定义一个自定义的
ConstantArray
类型 它包含一个数组,并且只有不可变的访问器方法 (全部转发到包含的数组):

对于映射,可以使用全局
map()
函数 (或
Array
map()
方法)并将结果转换回
ConstantArray

myArr = ConstantArray(map(myArr) { $0 * 2 })
myArr = ConstantArray(myArr.array.map { $0 * 2 })
extension ConstantArray {
    func map<U>(transform: (T) -> U) -> ConstantArray<U> {
        return ConstantArray<U>(elements.map(transform))
    }
}
或者为
ConstantArray
实现
map()
方法:

myArr = ConstantArray(map(myArr) { $0 * 2 })
myArr = ConstantArray(myArr.array.map { $0 * 2 })
extension ConstantArray {
    func map<U>(transform: (T) -> U) -> ConstantArray<U> {
        return ConstantArray<U>(elements.map(transform))
    }
}
同样,其他方法,如
filter()
sorted()

可以为
ConstantArray

实现您想要的对
数组
没有意义,因为它是一种具有值语义的值类型。变量的值就是数组——所以改变变量的能力和改变数组的能力在某种程度上是一样的

在语义上,以下各项之间没有区别:

myArr.append(42)
还有一些类似(虚构的):

在某种程度上,您可以想象对值类型变量的任何“修改”都可以实现为为变量分配一个全新的值。(可能不是这样做的,因为这样做效率很低,但从语义的角度来看,没有理由不能以这种方式实现。)


“可变性”的概念仅适用于引用类型,其中变量是指向实际对象的引用,并且实际对象可以在多个引用之间共享(因此通过一个引用的“变异”可以通过另一个引用看到)


对于引用类型,您可以根据需要执行任何操作,例如使用不可变的
不可变数组
类,然后如果您有
不可变数组
类型的
var
变量,则您可以构造一个全新的不可变数组,并将该变量更改为指向新数组,但无法创建任何特定的数组对象从共享引用中看到的“已更改”。

对分配给可变变量的不可变NSArray执行进一步操作返回不可变NSArrays?例如:
var arr=NSArray(1,2,3);arr=arr.map{$0*2}
。arr现在是可变的还是不可变的?哦,这很聪明。函数库一定是在swift中实现的。这是最干净的swift解决方案,但我非常讨厌它。我们又回到了Java的
集合。不可修改列表
。这是一个非常好的观点。我没有考虑数组(和字典)是swift中的一种值类型。实现了我在这个问题上的目标,即能够相信我的函数正在处理的集合不会在我背后发生变异。
myArr.append(42)
myArr = myArr.newArrayWithAppending(42)