The key here is (and always was going to be) the nil-coalescing operator. This lets you unwrap an Optional safely if it is not nil
, but if it is nil
, you substitute another value.
The issue with the question, however, is that it poses itself in an unSwifty way. You would never write a filtering function that takes an Optional String. You would write a filtering function that takes an Optional filtering function! Instead of limiting the caller to contains
and a String, you want to allow any type of array and any filtering function. That is the Swifty way to write this function.
And while we are at it, the function should not predetermine what is done with the members of the array either. That should be another function that the caller passes in!
Thus we end up with this far more general and much Swiftier statement of the goal:
func process<T>(_ arr: [T],
filtering filterPred: ((T)->Bool)? = nil,
processing processPred: ((T)->Void)) {
// ...
}
Okay! So let's write this function. The processing
part is easy; this is the predicate to a forEach
call. Like this:
func process<T>(_ arr: [T],
filtering filterPred: ((T)->Bool)? = nil,
processing processPred: ((T)->Void)) {
arr.forEach(processPred)
}
Very good! But we have neglected to deal with the filtering
function. Let's take care of that. Clearly, this is where the rubber meets the road. And just as clearly, it is evident that this is a function to be passed into filter
. But we can only do that by unwrapping if it is not nil
. What if it is nil
? The OP has specified that in that case we should let all element through the filter.
So consider a predicate function that is to be passed into filter
. What is the function that lets everything through? It is:
{ _ in true }
So that is what to put after the nil-coalescing operator! Therefore, this is the full answer:
func process<T>(_ arr: [T],
filtering filterPred: ((T)->Bool)? = nil,
processing processPred: ((T)->Void)) {
arr.filter(filterPred ?? { _ in true }).forEach(processPred)
}
And here are two tests:
let arr = [1,2,3,4]
self.process(arr) { print($0) }
self.process(arr) { $0 % 2 == 0 } processing: { print($0) }