Pulling back from closures specifically for a second: parentheses in Swift, and in many other languages, are used for grouping elements together:
- In an expression, parentheses group part of a sub-expression together to indicate precedence — e.g.,
x + y / 2
vs. (x + y) / 2
- In an expression, parentheses can also group multiple separate sub-expressions together into a tuple — e.g.,
(x, y)
- When calling a function/closure/method, parentheses are used to group the arguments to the function together
Parentheses of form (1) above are used for parsing, but don't change the meaning of code outside of the precedence of operations. For example:
let x: Int = 5
let y: Int = (5)
let z: Int = ((5))
x
, y
, and z
are all equivalent, and identical: the parentheses are grouping a sub-expression, but that sub-expression is just a singular value. (Why is this valid? Think: (x + y) / 2
; getting rid of / 2
yields (x + y)
; getting rid of + y
yields (x)
)
Here, x
, y
, and z
are Int
s, but they could easily all be values of a different type:
let x: () -> Void = function
let y: () -> Void = (function)
let z: () -> Void = ((function))
In this case, x
, y
, and z
are all function types which take no arguments and return nothing; wrapping up the value in parentheses doesn't do anything here either.
In order to call x
, y
, and z
, here, you use a separate pair of parentheses which go after the variable name, passing in the arguments internally — here I'm passing no arguments, so the parentheses are empty:
x()
y()
z()
This turns the references of x
, y
, and z
, into function calls, and are parens of form (3) above.
Putting the definitions of x
, y
, and z
together with their calls, you get the fact that
function()
(function)()
((function))()
are then also all equivalent. The parentheses around function
are grouping function
itself (doing nothing), and the parentheses that go after are grouping the parameters.