Function composition

In the previous section, we saw an example of higher-order functions that could accept two different functions and execute them in a predefined order. This function was not so flexible in the sense that it would break if we wanted to combine two accepted functions differently. Function composition can solve this issue and make it even more flexible. To present this concept, we will examine an example of non-functional composition first, and then we will introduce functional composition.

Suppose that, in our application, we need to interact with a backend RESTful API and receive a String value that contains a list of prices in order. The backend RESTful API is being developed by a third-party and is not designed properly. Unfortunately, it returns a String with numbers in it separated by commas, as follows:

"10,20,40,30,80,60" 

We need to format the content that we receive before using it. We will extract elements from String and create an array, and then we will append $ as currency to each item to use it in a table view. The following code example presents an approach to this problem:

let content = "10,20,40,30,80,60" 

func extractElements(_ content: String) -> [String] {
return content.characters.split(separator: ",").map { String($0) }
}

let elements = extractElements(content)

func formatWithCurrency(content: [String]) -> [String] {
return content.map {"($0)$"}
}

let formattedElements = formatWithCurrency(content: elements)

In this code example, we treated each function individually. We could use the result of the first function as an input parameter for the second function. Either approach is verbose and not functional. Additionally, we used the map function, which is a higher-order function, but our approach is still not functional.

Let's approach this problem in a functional way.

The first step will be to identify function types for each function:

  • extractElements - String -> [String]
  • formatWithCurrency - [String] -> [String]

If we pipe these functions, we will get the following:

extractElements: String -> [String] | formatWithCurrency: [String] -> [String] 

We can combine these functions with a functional composition and the composed function will be of type of String -> [String]. The following code snippet shows the composition:

let composedFunction = { 
data in
formatWithCurrency(content: extractElements(data))
}

composedFunction(content)

In this example, we define composedFunction, which is composed of two other functions. We can compose functions like this as each function has at least one parameter and return value.

This composition is like the mathematical composition of functions. Suppose that we have a function f(x) that returns y and a g(y) function that returns z. We can compose the g function as g(f(x)) -> z. This composition makes our g function take x as a parameter and return z as a result. This is exactly what we have done in our composedFunction.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset