I don’t know about you, but I often find myself casting objects in Swift. This used to involve writing code like this:
if let myDataSource = tableView.dataSource as? MyDataSource {
doSomething(to: myDataSource)
}
This is especially annoying when I’m using a functional programming style, as that entails writing a lot of functions, and casting parameters is a pain and makes for ugly code.
So, I wrote a function to do this for me:
public func optionalCast<T, U>(_ t: T) -> U? {
return t as? U
}
You can use it like this:
doSomething(to: optionalCast(tableView.dataSource))
presuming that doSomething(to:) accepts optionals (if not, see my post about an operator to handle that case). And, better, I turned this into an operator on a function:
prefix operator ~>
public prefix func ~><T, U>(f: @escaping (U) -> Void) -> (T) -> Void {
return { t in
if let cast: U = optionalCast(t) {
f(cast)
}
}
}
Now I can use this to easily create functions that accept an arbitrary parameter type, and pass things directly to it:
let doSomethingToDataSource: (UITableViewDataSource) -> Void = ~>doSomething(to:)
doSomethingToDataSource(tableView.dataSource)
Or, if you use functional programming operators from Prelude, you can make it even simpler:
tableView.dataSource |> ~>doSomething(to:)
This is especially useful when composing functions. Suppose a function returns an object which you only care about dealing with if it’s a specific subclass; then, using the Prelude library, you could do something like this:
let newFunction = self.createDataSource >>> ~>doSomething(to:)
which you can then easily add to your pipeline of functions for setting up your datasource.