magnuskahr

writing code

Syntactic-sugar: exclude

I am a fan of higher order functions in Swift, allowing for mapping, filtering, and reducing on sequences - like in the following example:

let points = [1.0, 1.5, -3.8, 0.5]
let positive = points.filter { $0 > 0 }
print(positive)

The above code will print: [1.0, 1.5, 0.5] because those are the doubles above 0. This is because of the closure given to filter(), and even though $0 > 0 can be easy to read, closures can become complex, why often declare them as a function:

func isPositive(_ number: Double) -> Bool {
    return number > 0
}
 
let points = [1.0, 1.5, -3.8, 0.5]
let positive = points.filter(isPositive)
print(positive)

Easy. But now, what if I wanted to get all the negative numbers? There is a couple of solutions:

  • I could create a corresponding isNegative(double) -> Bool function, but thinking about it, I would have to follow this pattern of creating a sorting function for both including and excluding on each parameter.
  • I could take a step back, and provide the filter with a closure: points.filter { !isPositive($0) }, but that again can become complex.

Exclude() - the long lost brother

That is why I created this little extension, which does the opposite of the filter function:

extension Sequence {
    func exclude(_ predicate: (Self.Element) throws -> Bool) rethrows -> [Self.Element] {
        return try self.filter { try !predicate($0) }
    }
}

We can see that it simply wraps a negation of filter, why it is syntactic sugar, but it allows us to now do the following:

let points = [1.0, 1.5, -3.8, 0.5]
let negative = points.exclude(isPositive)
print(negative)

Which I think is pretty neat.