3

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

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)
  }
}

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?

Ozgur Vatansever
  • 49,246
  • 17
  • 84
  • 119

1 Answers1

2

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.

matt
  • 515,959
  • 87
  • 875
  • 1,141
  • What is the difference between `forEach { push(element: $0) }` and `forEach(push(element:))`? – Ozgur Vatansever Aug 14 '23 at 12:41
  • Is this a trick question? One calls a method, the other refers to a method. – matt Aug 14 '23 at 12:54
  • No, of course it wasn't. I was trying to understand why the above code is working with the former, but not with the latter. both options aim to mutate self within a non-escaping closure. – Ozgur Vatansever Aug 14 '23 at 15:55
  • 1
    Well, that's why I refer you to the "closure cannot implicitly capture" error. It has to do with the under-the-hood implementation when this is a struct and the method being referred to is mutating. You can look at the source if you're really interested in the gory details. – matt Aug 14 '23 at 15:59