gpt4 book ai didi

swift - 为什么我的结构在方法链中变得不可变?

转载 作者:搜寻专家 更新时间:2023-10-31 22:53:26 25 4
gpt4 key购买 nike

在 Swift 中,我试图实现一个类似于 Ruby 中存在的方法的“tap”方法。

我想出了以下示例代码:

private protocol Tap {
mutating func tap(_ block: (inout Self) -> Void) -> Self
}

private extension Tap {
mutating func tap(_ block: (inout Self) -> Void) -> Self {
block(&self)
return self
}
}

extension Array: Tap {}

var a = Array(repeating: "Hello", count: 5)

a.tap {
$0.append("5")
}.tap {
$0.append("7")
}

print(a) // (Expected) => ["Hello", "Hello", "Hello", "Hello", "Hello", "5", "7"]

我不太熟悉可变函数、inout 参数或一般的 Swift,但上面的代码看起来应该对我有用。 tap 在未包含在方法链中时按预期工作。当我将它作为方法链的一部分包含时,如上例所示,Swift 编译器会报错:

Cannot use mutating member on immutable value: function call returns immutable value

谁能向我解释为什么这不起作用?谁能提供可行的解决方案并解释该解决方案为何有效?

编辑:

另一个示例用法是:

let user = User(fromId: someId).tap {
$0.firstName = someFirstName
$0.lastName = someLastName
}

tap 是来自 Ruby 的便利工具。我主要想了解为什么我的函数中的类型无法正常工作。

最佳答案

return self 返回原始数组的副本,而不是原始数组本身。在将此副本存储为 var 之前,它不能被改变。所以,这会起作用:

var b = a.tap {
$0.append("5")
}
b.tap {
$0.append("7")
}

但并非没有先将 b 存储为 var。当然,您不会一开始就创建一个 b,您只需像您已经指出的那样重复使用 a

因此,问题在于您可以完成一次tap,但不能链接tap。这是因为 self 的返回是隐式不可变的,并且您不能对不可变值调用可变函数。将 tap 更改为非变异函数可以获得您想要的:

private extension Tap {
func tap(_ block: (inout Self) -> Void) -> Self {
let copy = self
block(&copy)
return copy
}
}

var a = Array(repeating: "Hello", count: 5)

a = a.tap({$0.append("5")}).tap({$0.append("7")})

因为每次调用 tap( 都会返回由给定 block 修改的原始副本,您可以在不可变类型上调用它。这意味着您可以链接。

唯一的缺点是开头有新的a =

关于swift - 为什么我的结构在方法链中变得不可变?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54338042/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com