"If functions are essentially closures." This isn't true. Functions (and methods) are not the same thing as closures. Functions have all their free variables unbound. Closures have bound some or all of their free variables (closed over them, which is where the name "closure" comes from).
A "free variable" is any variable defined outside the scope of the function (including its formal parameters). The top-level function func f(x: Int)
has one free variable; when you call it, you must pass a parameter. A closure like { f(1) }
has no free variables. When you call it, you do not pass any parameters.
A method, like a function, does not capture anything. It is passed all of its free variables when it is executed. For example, when you make the call object.doThis()
, this is the same as calling Type.doThis(object)()
.
class X {
func doThis() {}
}
let x = X()
x.doThis()
X.doThis(x)() // Same thing
X.doThis(x)
is a function that returns a function. There's no magic here. All the free variables are provided during the call. Nothing is captured. (The "free variable" in the case you describe is self
, but that doesn't change anything. self
is not special, except that it gets a little syntactic sugar around it.)
This is different than a closure:
let c = { x.doThis() }
c()
When I call c()
, how does it know the value of x
? I may have returned c
and x
may be out of scope now. The system has to keep track of x
(including making a strong reference so it doesn't deallocate), and it does that by capturing it, or "closing over x" which raises the possibility of retain loops. So in c
, x
is bound. It is not free. You can't pass it when you call c()
.
self
is not special here. It's just another variable. [weak self]
in closures isn't special either. You can write [weak x]
just as well. The [...]
syntax is just the capture list.