Currying is a generic “technique of translating the evaluation of a function that takes multiple arguments into evaluating a sequence of functions, each with a single argument” (wikipedia). Swift supports currying as we see in the following example.
Let’s declare (and call) a simple function that takes two parameters (a String and and Int) as arguments and return a String:
1 2 3 4 |
func ageDescrOf(name : String, age : Int) -> String { return "\(name) is \(age) year old" } let ad = ageDescrOf("Carlo", 18) |
Using currying we can declare this function in such a way that it can be called as a sequence of single-parameter function calls.
1 2 3 |
func ageDescrOf2(name : String)(age : Int) -> String { return "\(name) is \(age) year old" } |
Note the multiple (…) in the declaration.
With this syntax the function ageDescrOf2 can be called in the following way:
1 |
let ad2 = ageDescrOf2("Carlo")(age: 18) |
On the other hand if we call it using only the first parameter, it returns another function of prototype (age : Int) -> String.
1 |
let ageOfCarlo = ageDescrOf2("Carlo") |
Now ageOfCarlo is a function of type: (age : Int) -> String, thus we can call it passing only the age parameter:
1 |
let ad2 = ageOfCarlo(age: 18) |
The result of this method (applied multiple times) is to transform an N parameters function call to a sequence of 1 parameter function calls.
Pros of using currying:
- the call of complex functions can be simplified using only the arguments we are interested in
- the evaluation of arguments is located in different zones of the code, where they are more context related
The external parameter name (bug?)
The more eagle eyed of you have noted a strange thing in the last line of code, we should call it without the name parameter (we didn’t declare one). But if we do so the compiler raises an error:
1 |
let ad3 = ageOfCarlo(18) // //<- error: Missing argument label 'age:' in call |
We regard this as a bug (see also this SO post) of the current Beta (5). And you?
Instance methods
Thanks to Ole Begemann for pointing us to the fact that instance method in swift are curried functions, with the first parameter of the function being the instance.
1 2 3 4 5 6 |
class MyClass { func doIt(a : Int) { } } let a = MyClass() MyClass.doIt(a)(3) // equal to a.doIt(3) |
Github complete code example.