DEV Community

Cover image for Higher Order Functions in Swift
Timothy Fosteman
Timothy Fosteman

Posted on • Edited on

1

Higher Order Functions in Swift

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 and flatMap 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:), and partition(by:) all reorder elements
recipes.sort {$0.prepTime < $1.prepTime }

recipes.sort { $0.label.uppercased() < $1.label.uppercased() }

Enter fullscreen mode Exit fullscreen mode
  • forEach visit each element
  • firstIndex(where:), lastIndex(where:), first(where:), last(where:), and contains(where:) answer "Does element exist ?"
bulletproofRice.ingredients.contains { $0.ingredient == "Raw Honey" }
Enter fullscreen mode Exit fullscreen mode
  • min(by:), max(by:) find the minimum or maximum of all elements
  • elementsEqual(_:by:) and starts(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 of prefix
  • removeAll(where:) remove the elements matching the condition
  • accumulate combine elements into an array. Alike reduce, 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. Alike firstIndex but doesn't halt on the first.
  • zip(sequence1:sequence2:) create a sequence of pairs built out of two underlying sequences.
Consider my Wild-Caught oneliner
let numbers: [Int] = [0, 1, 1, 2, 3, 4, 4]
var result: [[Int]] = numbers.isEmpty ? [] : [[numbers[0]]]
//Wild-Caught one-liner
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]]
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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.

That's the satori of modern programming languages.

Sentry growth stunted Image

If you are wasting time trying to track down the cause of a crash, it’s time for a better solution. Get your crash rates to zero (or close to zero as possible) with less time and effort.

Try Sentry for more visibility into crashes, better workflow tools, and customizable alerts and reporting.

Switch Tools 🔁

Top comments (0)

Image of Docusign

🛠️ Bring your solution into Docusign. Reach over 1.6M customers.

Docusign is now extensible. Overcome challenges with disconnected products and inaccessible data by bringing your solutions into Docusign and publishing to 1.6M customers in the App Center.

Learn more