1

In Swift, the only reference type available to a programmer is a class. We know that closures are objects as they store references to variables captured in the parent scope. Closures are also reference types, according to Apple's Swift Programming Language Guide. You can see that assigning a closure doesn't create a copy of a captured environment and creates a new reference to the existing environment like in this example:

func test1() {
  var x = 42
  let f = {
    print(x)
  }

  f() // prints 42

  // `g` stores a reference to `f`
  let g = f 

  x = 24

  g() // prints 24
}

Are closures implemented in the Swift compiler with a similar "infrastructure" used for implementing classes? Is there a code in the compiler internals hidden from language users that could have looked like this when exposed?

// pseudocode
final class Closure<ArgumentType, ReturnType> {
}

typealias ArgumentType -> ReturnType = Closure<ArgumentType, ReturnType>

If so, is there a separate treatment for throwing closures that looks like this?

// pseudocode
final class ThrowingClosure<ArgumentType, ReturnType> {
}

typealias ArgumentType throws -> ReturnType = Closure<ArgumentType, ReturnType>

The main question here is, can we consider a common closure a subclass of a throwing closure? Because it clearly looks like you can assign a common closure to a whatever place that expects a throwing closure type:

func test(f: () throws -> Int, g: () -> Int) {
  print((try? f())!)
  print((try? g())!)
}

// prints 4 and 2
test(f: { 4 }, g: { 2 })
Max Desiatov
  • 5,087
  • 3
  • 48
  • 56
  • 1
    https://stackoverflow.com/q/43171341/2976878 might be useful - though I haven’t updated my answer there since Swift 3, things may have changed in later versions of the language. – Hamish Sep 11 '18 at 10:17
  • "We know that closures are objects as they store references to variables captured in the parent scope." Structs can store things too. – newacct Sep 11 '18 at 16:54
  • "Closures are also reference types, because assigning a closure doesn't create a copy and creates a new reference to the existing closure like in this example:" How do you know it doesn't create a copy? Closures in Swift capture variables by reference, so if hypothetically the closure is a value type that is copied, it can copy the reference, and still access the same variable. Multiple closures can access and modify the same captured variable, and obviously multiple closures are separate things, so why couldn't multiple copies of the same closure access and modify the same captured variable? – newacct Sep 11 '18 at 17:04
  • @newacct this is [confirmed by the official Swift Programming Language Guide](https://docs.swift.org/swift-book/LanguageGuide/Closures.html#ID104), I've edited the original question to clarify that. – Max Desiatov Sep 11 '18 at 20:53
  • 2
    @MaxDesiatov: My point is, your example doesn't show that. It could be a value type and it can work the same way. Since closures are immutable, there is no semantic way to distinguish whether it's a reference type or value type. If the Swift "guide" claims such an example as showing that it's a reference type, it's wrong; it only shows that Swift closures capture variables by reference. – newacct Sep 11 '18 at 22:56
  • @newacct my point is that current wording of the question does not use the example to confirm closure semantic. This is confirmed by linking to the Guide hosted on official swift.org website maintained by the Swift core team. The example is used only to confirm that a new reference is created to existing environment and it's not copied. The fact that closures are reference types is not debated and I assume we can rely on the knowledge of Swift core team shared in the Guide. The question explicitly asks about implementation "in the Swift compiler", not about "semantic way to distinguish" it. – Max Desiatov Sep 13 '18 at 09:02

0 Answers0