繁体   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