Swift Closure / Lambda with Substitution Variables

Remember Objective-C, where you can use filteredArrayUsingPredicate on a NSArray in conjunction with a NSPredicate? Then you also remember, that it is possible to use substitution variables in the predicate which come in handy, when you have to re-use it in different methods.

In Swift, nothing blocks us from doing the same. However, using the built-in filter is more appealing. For example, consider the following data structure (initializers not shown):

class A
    let X : Int
    let Y : Int

Further, there is some function fun which returns an array of A, e.g. func getArray() -> [ A ]. Now, in order to filter the array, we can use filter and a closure (lambda):

var As = getArray()
As.filter({ (a: As) -> Bool in return (a.X == 0 && a.Y == 1) })

Since it is a closure, it can capture variables from outside, so we can replace the hardcoded 0 and 1 by a variable:

var As = getArray()

let x = 0
let y = 1

let Bs = As.filter({ (a: A) -> Bool in return (a.X == x && a.Y == y) })

// Do something with Bs

Now, the question is: how to re-use this lambda with a different set of x and y. Then answer is quite easy: make yourself a helper function! For example:

func makePredicate(#x: Int, #y: Int) -> (A -> Bool)
    return { (a: A) -> Bool in return a.X == x && a.Y == y }

This small function returns a lambda with captured variables x and y. You can call it directly with filter:

let Bs = As.filter(makePredicate(x: 0, y: 1))

This also works with every other function like map or sort. Happy filtering!

Leave a Reply