Note from Ray: This is an abbreviated version of a chapter from Swift by Tutorials released as part of the iOS 8 Feast to give you a sneak peek of what’s inside the book. We hope you enjoy!

When making the transition from Objective-C to Swift, it’s logical to map concepts you know in Objective-C onto Swift. You know how to create classes with Objective-C, and now you know the equivalent in Swift. There are, of course, some completely new features, such as generics and range operators, but these are still little more than refinements of what you already know. (OK, perhaps not so little!)

However, Swift does more than provide a better syntax for your applications. With this new language, you have the opportunity to change the way in which you tackle problems and write code. With Swift, functional programming techniques become a viable and important part of your programming toolkit.

Functional programming can be a theory-heavy topic, so this tutorial will introduce the topic by example. You’ll work through a number of programming examples using what will likely be the more familiar, imperative style, and then try your hand at solving the same problems using functional techniques.

Note: This Swift functional programming tutorial assumes you already know the basics of Swift development. If you are new to Swift, we recommend you check out some of our other Swift tutorials first.

What is Functional Programming?

Briefly put, functional programming is a programming paradigm that emphasizes calculations via mathematical-style functions, immutability and expressiveness, and minimizes the use of variables and state.

Since there’s minimal shared state and each function is like an island in the ocean of your app, it makes things easier to test. Functional programming has also come into popularity because it can make concurrency and parallel processing easier to work with. That’s one more thing in your toolbox to improve performance in these days of multi-core devices.

Its time to put the fun- into functional programming!

Simple Array Filtering

You’ll start with something quite easy: a simple bit of math. Your first task is to create a simple Swift script that finds all the even numbers between 1 and 10 (inclusive). A pretty trivial task, but a great introduction to functional programming!

Filtering the Old Way

Create a new Swift playground file and save it wherever you like. Replace the contents of the newly created file with the following code:

(If you can’t see the console output, remember that you need to show the Assistant Editor via the View/Assistant Editor/Show Assistant Editor menu option.)

This little script is very simple; the key points of the algorithm are as follows:

You create an empty (and mutable) array.

The for loop iterates over the numbers from 1 to 10 (remember “…” is inclusive!).

If the condition (that the number must be even) is met, you add it to the array.

The above code is imperative in nature. The instructions tell the computer how to locate the even numbers by giving it explicit instructions that use basic control structures, in this case if and for-in.

The code works just fine but the important bit—testing whether the number is even—is buried inside the for loop. There’s also some tight coupling, where the desired action of adding the number to the array is inside the condition. If you wanted to print each even number somewhere else in your app, there’s no good way to reuse code without resorting to copy-and-paste.

Functional Filtering

You’ll see that the above, functional code creates exactly the same result as the imperative version:

[2, 4, 6, 8, 10]

Let’s look more closely at the functional version. It’s comprised of two parts:

The Array(1...10) section is a simple and convenient way to create an array containing the numbers 1 through 10. The range operator 1...10 creates a Range you pass to the array’s initializer.

The filter statement is where the functional programming magic takes place. This method, exposed by Array, creates and returns a new array that contains only the items for which the given function returns true. In this example, isEven is supplied to filter.

You’re passing in the function isEven as a parameter to filter, but remember functions are just named closures. Try adding the following, more concise version of the code to your playground:

Again, verify that the results from all three approaches are identical. The above example demonstrates that the compiler infers the type of the parameter number and return types of the closure from its usage context.

If you like your code to be as concise as possible, take it one step further and try the following:

Note: The use of shorthand argument notation is a matter or preference. Personally, I think that for simple examples like the one above, shorthand notation is just fine. However, I’d opt for explicit argument names for anything more complicated. Compilers aren’t concerned with variable names, but they can make a world of difference to humans!

The functional version of this code is certainly more concise than the imperative equivalent. This simple example exhibits a few interesting features that are common to all functional languages:

Higher-order functions: These are functions that you pass as arguments to other functions. In this simple example, filter requires that you pass a higher-order function.

First-class functions: You can treat functions just like any other variable; you can assign them to variables and pass them as arguments to other functions.

Closures: These are effectively anonymous functions you create in-place.

You may have noticed that Objective-C also exhibits some of these features through the use of blocks. Swift, however, goes further than Objective-C in promoting functional programming with a mix of more concise syntax and built-in functional abilities such as filter.

The Magic Behind Filter

Swift arrays have a number of functional methods, such as map, join and reduce. What, exactly, goes on behind the scenes in these methods?

It’s time to look behind the magic of filter and add your own implementation.

The above is a generic function that takes as its inputs a source, which is an array of type T, and predicate, a function that takes an instance of T and returns a Bool.

The implementation of myFilter looks a lot like the imperative version you added at the start. The main difference is that you supply the condition being checked as a function rather than hard-code it.

Try out your newly added filter implementation by adding the following code:

evens = myFilter(Array(1...10)) { $0 % 2 == 0 }
println(evens)

Once again, the output is the same!

Challenge: The above filter function is global; why not see if you can make it a method on Array?

You can extend Array, but not Array<T>. This means that as you iterate over the items in the array via self, you’ll have to perform a cast.

Reducing

The previous example was a simple one, making use of a single functional method. In this section, you’ll build upon the last, showing how you can implement more complex logic using functional techniques.

Create a new Swift playground and get ready for your next assignment!

Manual reduction

Your task in this section is just a little more complicated: Take the even numbers between 1 and 10 and compute their sum. This calls for what is known as a reduce function, which takes a set of inputs and generates a single output.

I’m sure you are more than capable of working this one out yourself, but here it is anyway! Add the following to your playground:

The previous section covered the array construction and use of filter. The net result of these two operations is an array with five numbers, [2, 4, 6, 8, 10]. The new step in the above code uses reduce.

reduce is a tremendously versatile Array method that executes a function once for each element, accumulating the results.

To understand how reduce works, it helps to look at its signature:

func reduce<U>(initial: U, combine: (U, T) -> U) -> U

The first parameter is the initial value, which is of type U. In your current code, the initial value is 0 and is of type Int (hence U is Int in this case). The second argument is the combine function that is executed once for each element of the array.

combine takes two arguments: the first, of type U, is the result of the previous invocation of combine; the second is the value of the array element that is being combined. The result returned by reduce is the value returned by the last combine invocation.

There’s a lot going on here, so let’s break it down step by step.

In your code, the first reduce iteration results in the following:

The inputs to combine are the initial value, 0, and the first item in the input array, which is 2. combine sums these values, returning 2.
The second iteration is illustrated below:

On the second iteration, the inputs to combine are the result from the previous iteration and the next item from the input array. Combining them results in 2 + 4 = 6.

Continuing this process for all the items in the array gives the following inputs and outputs:

The number highlighted in the bottom-right corner is the overall result.

This is quite a simple example; in practice, you can perform all kinds of interesting and powerful transformations with reduce. Below are a few quick examples.

This code uses reduce to find the maximum number in an array of integers. In this case, the result is rather obvious! Remember that here, total is really just the result of max of the last iteration of reduce.

If you’re struggling to see how this works, why not create a table like the one above where you compute the inputs and output of combine (i.e., the closure) for each iteration?

The examples you’ve seen so far all reduce arrays of integers into single integer values. Of course, reduce has two type parameters, U and T, which can be different and certainly don’t have to be integers. This means you can reduce an array of one type into a completely different type.

The above adds a myReduce method to Array that mimics the built-in reduce function. This method simply iterates over each item in the array, invoking combiner at each step.

To test out the above, replace one of the reduce methods in your current playground with myReduce.

At this point, you might be thinking, “Why would I want to implement filter or reduce myself?” The answer is, “You probably wouldn’t!”

However, you might want to expand your use of the functional paradigm in Swift and implement your own functional methods. It’s encouraging (and important!) to see and understand just how easy it is to implement powerful methods like reduce.

Building an Index

It’s time to tackle a more difficult problem, and that means it’s time to open a new playground. You know you want to!

In this section, you’re going to use functional programming techniques to group a list of words into an index based on the first letter of each word.

The Entry typealias defines the tuple type for each index entry. Using a typealias in this example makes the code more readable, removing the need to repeatedly specify the tuple type in full. You’re going to add your index-building code in buildIndex.

This function has two halves, each with its own for loop. The first half iterates over each of the words to build an array of letters; the second iterates over these letters, finding the words that start with the given letter, to build the return array.

The playground now outputs an array of uppercase letters, each one corresponding to a word in the input array.

[C, C, F, D, M, G, M]

In the previous sections, you encountered filter and reduce. The above code introduces map, another functional method that’s part of the array API.

map creates a new array with the results of calls to the supplied closure for each element in the supplied array. You use map to perform transformations; in this case, map transforms an array of type [String] into an array of type [Character].

The array of letters currently contains duplicates, whereas your desired index has only a single occurrence of each letter. Unfortunately, Swift’s array type doesn’t have a method that performs de-duplication. It’s something you’re going to have to write yourself!

In the previous sections, you saw how easy it is to re-implement reduce and filter. It will come as no surprise that adding a de-duplication method of your own isn’t tricky, either.

Now that you have an array of distinct letters, the next task in building your index is to convert each letter into an Entry instance. Does that sound like a transformation? That’ll be another job for map!

In the second half of the function, there’s now a nested call to filter inside map. That will filter the list of words for each distinct letter, and thus identifies the words starting with the given letter.

The above implementation is already more concise and clear than its imperative equivalent, but there’s still room for improvement: this code extracts and capitalizes a word’s first letter multiple times. It would be good to remove this duplication.

If this were Objective-C code, you would have a few different options at your disposal: You could create a utility method that performs this functionality, or perhaps you could add this method directly to NSString via a class category. However, if you only ever need to perform this task within buildIndex, a utility method lacks semantic clarity and using a class category is overkill.

The above code adds a firstLetter function that is nested within buildIndex and as a result, is entirely local to the outer function. This takes advantage of Swift’s first-class functions that you can treat much like variables, allowing for assignment and scoping.

The new code removes the duplicate logic, but there’s even more you can do to clean up buildIndex.

The first map step that constructs the array of letters takes a closure whose signature is (String) -> Character. You may notice this is exactly the same signature as the firstLetter function you just added, which means you can pass it directly to map.

Making use of this knowledge, you can rewrite the function as follows:

The end result is concise, yet highly expressive.
Perhaps you’ve noticed an interesting side effect of the functional techniques you have employed so far. While your imperative solutions have relied on variables (as defined using the var keyword), you’ve defined everything in the functional equivalents as constants (via let).

You should strive for immutability; immutable types are easier to test and aid concurrency. Functional programming and immutable types tend to go hand in hand. As a result, your code will be more concise as well as less error-prone. And it will look cool and impress your friends!

Challenge: Currently, buildIndex returns an unsorted index; the order of the Entry instances depends on the order of the words in the input array. Your challenge is to sort the index into alphabetic order. For the example array of strings, this would give the following output:

Swift’s Array type has a sort method, but this method mutates the array rather than returning a new, sorted instance, and it requires a mutable array on which to operate. In general, it’s safer to deal with immutable data, so I would advise against using this method! As an alternative, use the sorted method that returns a second sorted array.

Where To Go From Here?

Congratulations, you now have hands-on experience with functional programming in Swift! Not only did you learn how to use functional methods like map and reduce, but you learned how to implement them yourself, and how to think in a functional way.

If you want to learn more about functional programming, check out the full chapter in Swift by Tutorials, where I go a bit further and cover partial application of functions and currying.

I hope to see you experiment with functional programming techniques in your own apps. If you have any questions or comments along the way, please join the forum discussion below!

Colin Eberhardt has been writing code and tutorials for many years, covering a wide range of technologies and platforms. Most recently he has turned his attention to iOS. Colin is CTO of ShinobiControls, creators of charts, grids and other powerful iOS controls.