逃逸自动闭包捕获 ‘inout’ 参数 ‘self’

huangapple go评论100阅读模式
英文:

Escaping autoclosure captures 'inout' parameter 'self'

问题

我一直在使用枚举类型编写一个简化版的堆栈:

    public enum Stack<Element> {
      case empty
      indirect case node(value: Element, next: Stack<Element>)
    
      public init(_ elements: Element...) {
        self = .empty
        elements.reversed().forEach(push)
      }
    
      public mutating func push(element: Element) {
        self = .node(value: element, next: self)
      }
    }

然而,在初始化器处我遇到了以下错误,并且无法理解,因为 `self` 是一个值类型,而 `forEach` 的主体不是逃逸闭包:

> 逃逸自动闭包捕获了 `inout` 参数 `self`

当我在主体内明确地编写该方法时,就不再出现上述错误。

    elements.reversed().forEach { push(element: $0) }

你能帮我理解为什么吗?
英文:

I've been writing a simplified version of Stack using enum types:

public enum Stack&lt;Element&gt; {
  case empty
  indirect case node(value: Element, next: Stack&lt;Element&gt;)

  public init(_ elements: Element...) {
    self = .empty
    elements.reversed().forEach(push)
  }

  public mutating func push(element: Element) {
    self = .node(value: element, next: self)
  }
}

However, I got stuck receiving the below error at initializer and couldn't figure out why since self is a value type and forEach's body is not an escaping closure:

> Escaping autoclosure captures 'inout' parameter 'self'

When I explicitly write the method inside the body, the error in question is gone.

elements.reversed().forEach { push(element: $0) }

Can you help me understand why?

答案1

得分: 2

这实际上与臭名昭著的“闭包无法隐式捕获可变 self 参数”错误是一样的,只是以另一种方式呈现。这是因为pushmutating的结果。

通过替换一个虚假示例很容易确认这一点:

public init(_ elements: Element...) {
    self = .empty
    elements.reversed().forEach(push)
}

public func push(element: Element) {
}

唯一的区别是我们去掉了关键字mutating

英文:

This is actually the same as the infamous "closure cannot implicitly capture a mutating self parameter" error in another guise. It is a consequence of the fact that push is mutating.

It is easy to confirm this by substituting a fake example:

public init(_ elements: Element...) {
    self = .empty
    elements.reversed().forEach(push)
}

public func push(element: Element) {
}

The only difference is that we took away the keyword mutating.

huangapple
  • 本文由 发表于 2023年8月10日 21:18:30
  • 转载请务必保留本文链接:https://go.coder-hub.com/76876106.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定