Apple’s programming language Swift includes several features commonly used in functional programming but unheard of in more mainstream languages. This blog post explores the lesser-known feature known as curried functions. I first encountered currying when studying the functional language Haskell, which is fundamentally based on function currying. Swift makes function currying available but a developer is never required to make use of it. It’s just another tool in a Swift developer’s toolbox.
The basic idea behind currying is that a function can be partially applied, meaning that some of its parameter values can be specified (bound) before the function is called. Partial function application yields a new function. That new function’s signature is based on the original function’s signature, but the bound parameters are not in the parameter list.
For example, suppose the original function’s parameter list is a String and an Int. If you bind the String parameter, you get back a new function whose parameter list only includes an Int. When you call that partially applied function and pass it an Int value, the function still has the bound String parameter value available to it.
Another way to think about currying is to contrast it to using a function with a default parameter value. In Swift a function’s parameters can have default values specified in the function declaration. If you call a function and don’t provide an argument for a parameter, that parameter’s default value will be passed to the function (assuming the parameter was given a default value by the function’s author). A default parameter value is a compile-time binding between a parameter and a constant value. A new default value cannot be assigned to a parameter at run-time. In contrast, currying effectively allows you to specify a parameter’s default value at run-time. The difference is that partially applying a function results in a new function being born. Only that new function knows the value of the bound parameter. Unlike using a default parameter, code which calls that new function cannot specify a different value for the bound parameter. Once it has been bound via partial function application, that parameter value is set in stone.
Here is a simple example showing the similarities and differences between using default parameter values and curried functions. The following code sample shows how to append a separator to the end of a string. The first function in the code listing uses a default value of “\n” for the separator parameter. Later in the code a different separator, whitespace, is used instead of a newline.
Using a Default Parameter Value
The output created by running this code is shown below:
The first one's free kid. I second that motion! Measure thrice, cut once. The first one's free kid. I second that motion! Measure thrice, cut once.
The next code listing shows how to accomplish the same thing using function currying. Note that when the appendSeparator method is called it returns a new function, not a String. This new function has the separator parameter bound to whatever String was passed to the appendSeparator function. The new function takes a String and returns a String which ends with the separator passed to appendSeparator.
Using a Curried Function
This example is trivial but it shows the essential concept of function currying in action. Binding some of a function’s parameters to create a simpler function makes it is possible to restrict knowledge of what parameter values should be used to only the places in an application that should have that knowledge. This can enable classes to be selectively ignorant about certain aspects of how a function should be used, and reduce coupling between collaborating objects.