woensdag 23 maart 2016

Closures

In Swift you can see functions more or less as variables. However, the variables in this case do not contain a value. In stead it contains a block with 1 or more tasks. Functions do not have a datatype like ‘normal’ variables but a function type. A closure is actually a function without a name.

Why should we use closures? They seem redundant. Everything you can do with closures you can also do with functions.

As it turns out closures can be passed as arguments to functions and closures can also be returned as functions. You can pass a block of tasks to a function or you can let a function return a block of tasks. Also the code is more compact dan a function. The lesser the code the less errors you can make.

Example:
var dutchOldReadingLessons = [ "aap", "noot", "mies", “wim", "zus", "jet", "teun", "vuur", "gijs", "lam", "kees", "bok", "weide", "does", "hok", "duif", "schapen"]

print(dutchOldReadingLessons)

dutchOldReadingLessons = dutchOldReadingLessons.sort(
  {
    print("\($0) or \($1): ")
    if $0 < $1 {print("\($0) comes first")
      return true
    }
    else {
      print("\($1) comes first")
      return false}
})


























In this Playground an array method is used: sort(). This method returns a sorted array and expects an argument: a closure.

The sort() method is told, via a closure, to how it must sort. The method sort() walks through the array and calls the closure with 2 elements of the array $0 < $1. The closure has to tell if the first element (true or false) has to be placed before or after the second element. By the way, if you look in the console and look what the closure prints for the 2 elements in the array, it does not have to necessarily start with ‘aap or noot:’. Swift decides by it self which 2 elements it takes to compare. If the closure has calculated that the first element has to appear before the second one it returns true. If the first has to go after the the second the closure returns false.

Sort() is responsible for sorting the array but it needs help. In the closure it should be clear so that sort() knows which of the 2 elements in the array comes before the other.

The sort declaration looks like this:

func sort(isOrderedBefore: (T, T) -> Bool) -> [T]

The part between parenthesis is wat sort expects. The argument ‘isOrderedBefore’ is of the function type (T, T) -> Bool. From ‘-> Bool’ you can read that the closure wil return a Bool (true or false) after the compare operation.

From the last ‘->’ you can see that the argument should be a closure that returns an array.
Between parenthesis you see 2 T’s. This means that the closure expects two arguments. T means that it can be any data type. It can be String, Int or Double. (T, T) means that the closure expects 2 arguments of the same type.
The return value [T] means that the datatype wil be the same as the one that was given as argument.

In above example sort() was used. But instead of sort there are also other methods that can be used:
filter()
reduce()
map()

A Closure can also return a function.
The following function is returning another function as its result which can be later assigned to a variable and called.

func jediTrainer () -> ((String, Int) -> String) {
  func train(name: String, times: Int) -> (String) {
    return "\(name) has been trained in the Force \(times) times"
  }
  return train
}
let train = jediTrainer()
train("Obi Wan", 3) 







Bron: Apps bouwen met Swift Versie 2.16 (januari 2016), Roelf Sluman.