Closures in Swift

Posted on 6/19/2014 @ 12:22 AM in #Swift by | Feedback | 1116 views

Closures most frequently used in JavaScript, are self contained blocks of functionality that isolate you from the global namespace, and can be passed around as blocks. Closures are so cool, they deserve their own blogpost.

Closures can be of 3 types,

  1. Global functions that can have a name and do not capture values
  2. Nested functions with a name that capture values from their encosing function
  3. Unnamed Closure expressions that capture values from their surrounding context

Closures give you an immense amount of flexibility in how you wish to express your intent.

For instance, lets say, I want a generic math method that takes two integers, and returns an integer. That would be like (Int, Int) –> Int. And now I wish to apply this on a sequence of numbers. Say an array.
The challenge here is, I want to give the consumer of my method to specify flexibility in what method they wish to use. As an example, this code,

   1:  func AddNumbers(a:Int, b:Int) -> Int {
   2:     return a + b
   3:  }
   5:  func MultiplyNumbers(a:Int, b:Int) -> Int {
   6:      return a * b
   7:  }
   9:  func CumulativeMath(inputNumbers:Int[], mathMethod:(Int, Int) -> Int) -> Int {
  10:      var toReturn = 0
  11:      for number in inputNumbers {
  12:          toReturn = mathMethod(toReturn, number)
  13:      }
  14:      return toReturn;
  15:  }
  17:  var DoMath: (Int, Int) -> Int = AddNumbers
  18:  var numbers = [1,2,3,4,5]
  20:  CumulativeMath(numbers, DoMath)

As you can see here, I can with one line of code change the DoMath from Add to Multiply. i.e. I can change the “algorithm” very easily. What closures allow me to do, they allow me to specify my own function right inline, like this -

   1:  CumulativeMath(numbers, {(a:Int, b:Int) -> Int in
   2:          return a-b
   3:      })

Whoaa! Take a deep breath! What the hell did I just do there? Instead of specifying a variable that had a function type, and then passing in the variable, I basically created the function right there and passed it in right there. Neat!

Here is a simpler example to help digest the concept,

   1:  var DoMath2: (Int, Int) -> Int = {(a:Int, b:Int) -> Int in
   2:      return a-b
   3:  }
   4:  DoMath2(2,3)

So basically, now I can ‘on the fly’ craft up logic and pass it in.

And the above syntax can be further simplified as below,

   1:  var DoMath2: (Int, Int) -> Int = {(a, b) in return a-b}
   2:  DoMath2(2,3)

What I just did there, I am inferring the types from the context. In fact, I don’t even have to write variable names, I can simply do the below,

   1:  var DoMath2: (Int, Int) -> Int = {$0-$1}
   2:  DoMath2(2,3)

Now what will really blow your mind is the crazy short syntax, like this,

   1:  CumulativeMath(numbers, -)

Imagine this in a sorting method, or iteration method to find items, etc.! Basically the operator can work as a function.

Sound off but keep it civil:

Older comments..