Function Currying in Swift

Introduction

Currying is a feature found in most modern programming languages. It translates a single function with multiple arguments into a series of functions each with one argument. In essence, this enables for storing functions in variables and creating functions that return functions.

While it may seem like a strange concept at first, it is a powerful technique that can be very useful at times. In this tutorial, I am going to show you how to take advantage of function currying in Swift.

1. Function Currying with Classes

Before defining our own custom functions, I am first going to show you a simple example of currying in Swift using classes.

Open Xcode, create a new iOS or OS X playground, and add the following code to it:

We define a basic class with one property and one instance method or function. We also create an instance of the class, car1. We can call the accelerateBy(_:) method of our Car instance with the following code:

There is, however, another way of executing this method through the use of function currying. In the above example, you call the method directly on car1 despite the method actually being defined in the Car class. The method we have written is not specific to the car1 instance, but rather the Car class. When you call this method, what is really happening is that Swift first goes to the Car class, retrieves the accelerateBy(_:) method, tells the method which instance is being used, and then executes an altered method specific to that instance. To show you how this works, add the following line to your playground:

What we are doing here is accessing the accelerateBy(_:) method of the Car class and passing, as a parameter, which instance we want this function to be executed on. In your playground's sidebar, you can see that the result of this method is another function.

A new function is returned

What this (Function) result represents is actually a new accelerateBy(_:) method specific to the car1 instance. This returned function is unique in that it specifically references car1's speed property rather than the generic method you defined earlier, which can reference the speed property of any Car instance.

As you would expect, we can pass new parameters to this returned function in order to execute it as we usually do. Add the following line of code to your playground:

With this code, we pass 10 as a parameter into the unique accelerateBy(_:) method and get car1's current speed returned as a result.

Function currying at work

Congratulations! You just took advantage of function currying in Swift for the very first time.

In addition to currying together multiple functions, the Function result that your code is returning can also be stored into a variable. This allows you to store and quickly reuse the accelerateBy(_:) method specific to your car1 instance. Add the following lines to your playground:

You can see that variable a now behaves like any other globally defined function. The advantage is that it is specific to a particular Car instance, which can be defined at run time rather than compile time. In your playground, you can see the expected outputs being displayed in the sidebar.

Results from stored function

Lastly, I am going to show you how you can return a function from another function by reimplementing the behavior of the Car class that we have just looked at. We are going to do this by defining a function that returns another function. In your code, this function could look something like this:

We define the someFunction(_:) function, which accepts an AnyObject parameter and returns another function that also accepts an AnyObject parameter that returns an AnyObject result. This type of function definition can look very confusing and daunting at first. To simplify it, we can take advantage of the typealias keyword in Swift to map a new name to any data type.

Add the following code to your playground:

By using typealias to map the name of IntFunction to the (Int) -> Int data type, we have greatly simplified the accelerationForCar(_:) function definition. The (Int) -> Int data type simply represents a function that accepts an Int parameter and returns an Int value.

This new function uses the built-in behavior of the Car class to return an IntFunction object that can then be stored in a variable and used like we did before.

2. Currying Custom Functions

While the built-in function currying behavior in Swift is very useful, you may wish to create your own functions that aren't related to classes. For this part of the tutorial, we are first  going to use the example of a function that multiplies another number by a constant value.

Imagine that you want to create a function that accepts a single input number and multiplies that by 5. This simple function could look like this:

Now imagine that you need a similar function, but you need it to multiply by 10 rather than 5. Then you need another function to multiply by 20. While you could create three similar functions and name them multiplyBy5multiplyBy10, and multiplyBy20, this could be handled much better using function currying.

Add the following code snippet to your playground:

We define the multiplyBy(_:) function that accepts an Int as its only parameter and returns a function of type IntFunction, the data type we defined earlier in this tutorial. In this function, we define another function, nestedMultiply(_:). We nest this function within the first so that it cannot be executed outside of the scope of the multiplyBy(_:) function and has access to the a input parameter.

The three lines below the function definition are simple examples of how you can curry the functions together.

Custom function currying results

While you can create functions for currying using nested functions, you can also create them using closures or by defining multiple sets of parameters. As an example, add the following code snippet to your playground:

As you can see, these two new functions can be curried together in the same way as all the other functions have been throughout this tutorial. The only exception is that, with the function defined with two sets of parameters, you must explicitly name the second parameter.

There is no limit to the number of levels of function currying you can implement within your code. The following code shows an example of three curried functions and how it differs over a single function with three parameters.

The main difference between these two multiplication functions is that the curried version can effectively be paused and stored in a variable after the first or second parameter has been processed. This makes the function very easy to reuse and pass around as an object.

Conclusion

Function currying in Swift is a difficult concept to grasp, but, at its core, it's basically about two key concepts:

  • creating functions that return other functions
  • reducing functions with multiple arguments into a series of functions each with one argument

There are a variety of ways to curry functions together and, while only the Int data type was used in this tutorial, the same processes can be used with any data type in your Swift projects. This enables for functions to be stored in variables and be used many times throughout your code.

As always, please be sure to leave your comments and feedback below in the comments.

Tags:

Comments

Related Articles