Swift - Using Closures In Your Functions

Introduction

Suppose you have a function that performs a bubble sort:


func bubbleSort(inout items:[Int])  {
    for var j=0; j<items.count-1; j++ {
        var swapped = false
        for var i=0; i<items.count-1-j; i++ {
            if items[i] > items[i+1] {
                var temp = items[i+1]
                items [i+1] = items [i]
                items[i] = temp
                swapped = true
            }
        }
        if !swapped {
            break
        }
    }
}

The bubbleSort() function sorts an array of Int values in ascending order like this:

var numbers = [6,7,8,9,2,1,3,4,5]
bubbleSort (&numbers)
print(numbers)  //[1, 2, 3, 4, 5, 6, 7, 8, 9]

The bubbleSort() function is hardcoded to sort the numbers in ascending order.

Adding closure

The compareFunction() function takes two Int arguments and returns a Bool value and thus it has the following function type:

(Int, Int) -> Bool

We can use closure so that the actual comparison of the numbers can be left to the caller of this bubbleSort() function.

When the bubbleSort() function is updated to use closure, it looks like this:


func bubbleSort(inout items:[Int],  compareFunction:(Int, Int)->Bool )  {
    for var j=0; j<items.count-1; j++ {
        var swapped = false
        for var i=0; i<items.count-1-j; i++ {
            if compareFunction(items[i],items[i+1])  {
                var temp = items[i+1]
                items [i+1] = items [i]
                items[i] = temp
                swapped = true
            }
        }
        if !swapped {
            break
        }
    }
}

To sort in descending order, simply pass in a closure like this:

bubbleSort(&numbers,
     {
          (num1:Int, num2:Int) -> Bool in
             return num1 < num2
     }
)

To sort in ascending order, simply pass in a closure like this:

bubbleSort (&numbers,
     {
         (num1:Int, num2:Int) -> Bool in
             return num1 > num2
     }
)

When you apply type inference and remove the named argument, you can reduce the preceding code to the following:

bubbleSort(&numbers,  { $0 > $1 } )

Related Topic