Parameterizing behaviour with functions in other HOCs
These transforming HOCs like map
, filter
are so useful for the reason of them having the transformation function acting inside, specified by the programmer.
This pattern of parameterized behaviour is found throughout the standard library. Array
, and other collections, have several useful HOCs

map
andflatMap
transform elements 
filter
include only certain elements 
allSatisfy
test all elements for condition 
reduce
fold the elements into an aggregate value 
sort(by:)
,sorted(by:)
,lexicographicallyPrecedes(_:by:)
, andpartition(by:)
all reorder elements
recipes.sort {$0.prepTime < $1.prepTime }
recipes.sort { $0.label.uppercased() < $1.label.uppercased() }

forEach
visit each element 
firstIndex(where:)
,lastIndex(where:)
,first(where:)
,last(where:)
, andcontains(where:)
answer "Does element exist ?"
bulletproofRice.ingredients.contains { $0.ingredient == "Raw Honey" }

min(by:)
,max(by:)
find the minimum or maximum of all elements 
elementsEqual(_:by:)
andstarts(with:by:)
compare elements of collections 
split(whereSeparator:)
break up the elements into multiple arrays 
prefix(while:)
take elements from the start as long as the condition holds true 
drop(while:)
drop elements until the condition holds true, return the rest. The inverse function ofprefix

removeAll(where:)
remove the elements matching the condition 
accumulate
combine elements into an array. Alikereduce
, but returns multiple times after each action. 
count(where:)
count the number of elements that match 
indices(where:)
return a list of indices matching the condition. AlikefirstIndex
but doesn't halt on the first. 
zip(sequence1:sequence2:)
create a sequence of pairs built out of two underlying sequences.
Consider my WildCaught oneliner
let numbers: [Int] = [0, 1, 1, 2, 3, 4, 4]
var result: [[Int]] = numbers.isEmpty ? [] : [[numbers[0]]]
//WildCaught oneliner
for (previous, current) in zip(numbers, numbers.dropFirst()) {
previous == current ? result[result.endIndex  1].append(current) : result.append([current])
}
result // [[0], [1, 1], [2], [3], [4, 4]]
What it does, or, I think it does, is splits an array into groups of adjacent equal elements.
If to put it succinctly into an extension
extension Array {
func split(where condition: (Element, Element) > Bool) > [[Element]] {
var result: [[Element]] = numbers.isEmpty ? [] : [[self[0]]]
for (previous, current) in zip(self, self.dropFirst()) {
if condition(previous, current) {
result.append([current])
}
else {
result[result.endIndex  1].append(current)
}
}
return result
}
}
result = numbers.split { $0 != $1 }
result // [[0], [1, 1], [2], [3], [4, 4]]
result = numbers.split(where: !=)
result // same result
The overall idea is to remove as much of boilerplate as possible. Several of these functions have default implementation: sort
, for example, sorts in ascension; contains
takes a value to check for.
Discussion