Last week started with an interesting concept about instance methods and currying in swift, Instance methods in swift are curried functions that takes the object instance as its first argument.

It seems that function currying is going to be a big part of our daily life as we start incorporating swift in our daily life iOS development, It is important to explore the different ways that we can create and call curried functions, and how to curry and uncurry a function.

lets start with a normal swift function that adds two numbers

func add(a: Int, b: Int) -> Int {
  return a + b
}

This function can be called let total = add(1, 2) in order to rewrite it in a curried format we have to separate each argument in its own parentheses.

func add(a: Int)(b: Int) -> Int {
  return a + b
}

The above function is now a curried function, we can partially apply it, and execute it on multiple steps

let firstStep = add(1)
let total = firstStep(b: 2)

The call to add(1) returns a function (closure) that takes one Int argument and return an Int value, the type of this function will be Int -> Int, it means that we partially applied the function on the first step and then partially applied it on the second.

We can also partially apply the two steps of the method in the same line

let total = add(1)(2)

Currying and Uncurrying a function

There are two ways to convert a normal function to a curried one. The first is to create a curried function with the same arguments and call the not curried function inside it.

func addCurried(a: Int)(b: Int) -> Int {
  return add(a, b)
}

addCurried is a curried function that calls the normal function inside it.

The Second way is to create a function that accepts 1 argument and returns a closure that accepts all the original not curried function arguments except the one passed to the wrapper function.

func addCurried2(a: Int) -> (Int) -> Int {
  return { (b: Int) in
    add(a, b)
  }
}

Calling addCurried2 will return a closure that accepts another argument, when calling this closure, both the first argument passed to the addCurried2 and the argument passed to the closure will be passed to add function.

In order to uncurry a function we just create a new function that takes the same argument of the curried one, and internally call the curried function passing all the arguments at once

func addNotCurried(a: Int, b: Int) -> Int {
  return addCurried(a)(b: b)
}