簡體   English   中英

為什么我的結構在方法鏈中變得不可變?

[英]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(&copy)
        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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM