[英]Why does my struct become immutable in a method chain?
在Swift中,我試圖實現一個方法“tap”,類似於Ruby中存在的方法。
我想出了以下示例代碼:
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編譯器抱怨:
不能在不可變值上使用變異成員:函數調用返回不可變值
任何人都可以向我解釋為什么這不起作用? 任何人都可以提供有效的解決方案並解釋該解決方案的原因
另一個示例用法是:
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(©)
return copy
}
}
var a = Array(repeating: "Hello", count: 5)
a = a.tap({$0.append("5")}).tap({$0.append("7")})
因為每次調用tap(
返回由給定塊修改的原始副本,你可以在不可變類型上調用它。這意味着你可以鏈接。
唯一的缺點是新的a =
開頭。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.