Curried Functions In SWIFT

Currying can be a difficult concept to grasp. Let’s start with a simple example.

 

func sum(a1: Int, a2: Int) -> Int {

return a1 + a2

}

var sum1 = sum(1,2)

 

That’s easy and straightforward sum function. If we just look at type of function sum, we can see that it has a type of (Int, Int) -> Int. So it takes 2 parameters of the type Int, and returns an Int. Now let’s declare function which takes Int parameter and returns another function which takes Int and returns Int.

 

func curriedSum(a1: Int) -> (Int) -> Int {

return { a2 in a1 + a2 }

}

 

 

As name of this function suggests it’s curried function. Curried function is just function that takes one parameter and returns another function which takes another parameter. And in common case the last function could return another function and so on.

How this curriedSum function could be used?

 

var sum2 = curriedSum(1)(10) // sum2 will be 11

 

 

First call curriedSum(1) returns function. That’s why another brackets follow for another call of function returned from the first call curriedSum(1)(10). And the last call returns Int.

Why anyone could prefer curriedSum(1)(10) to more usual sum(1, 10) which produces same results? The answer is because curried functions allow doing some useful tricks.

Provided we have curriedSum function declared we could easily produce new function from it:

 

var increment = curriedSum(1)

var decrement = curriedSum(-1)

 

 

If you remember curried function curriedSum returns a function, so increment and decrement will be functions which take Int and return Int. Now increment and decrement functions could be used as regular functions:

 

let i = increment(15)

let j = decrement(10)

 

 

To make it more evident that increment and decrement are functions we could not rely on type inference of Swift but include type to declarations:

 

var increment : (Int)->Int = curriedSum(1)

var decrement : (Int)->Int = curriedSum(-1)

 

 

Brackets around (Int) underline it’s parameter of a function. But they are not necessary:

 

var increment : Int->Int = curriedSum(1)

var decrement : Int->Int = curriedSum(-1)

 

 

That’s whole trick with curried functions – they allow as produce new functions easily from another functions.

Let’s return to how curriedSum is used. It’s usage looks like a chain of calls:

 

let n = curriedSum(5)(17)

 

 

That’s why Swift gives as a way to declare curried function close to how it will be used.

 

func curriedSum(a1: Int)(_ a2: Int) -> Int {

return a1 + a2

}

 

 

This declaration gives as curriedSum which is has same type and works the same as variant we declared and used before.

 

func curriedSum(a1: Int)(_ a2: Int) -> Int {

return a1 + a2

}

var sum2 = curriedSum(1)(10) // sum2 will be 11

var sum3 = curriedSum(10)(20) //sum3 will be 30

var sum4 = curriedSum(7)(30) //sum4 will be 37

var increment : Int->Int = curriedSum(1)

var decrement : Int->Int = curriedSum(-1)

let i = increment(15) // i will be 16

let j = decrement(10) //j will be 9

 

 

Trick with currying functions could be applied not only to pure functions but to instance functions as well. Let’s think of simple BankingAccount class which tracks account balance and allows deposit money into account.

 

class BankingAccount {

var balance: Double = 0.0

func deposit(amount: Double) {

balance += amount

}

}

let account = BankingAccount()

account.deposit(100) // 100 deposited

 

 

Now think of deposit instance function as of function with takes parameter of type BankingAccount and returns function. The last function takes Double and returns nothing. Doesn’t this remind you curried functions?

 

let depositor = BankingAccount.deposit

 

 

This declare function depositor with the only parameter of type BankingAccount. Provided we have some account we could deposit money into it with call depositor(account)(someMoney):

 

depositor(account)(100)

 

 

We could go further and make of it a function which gives as convenient way to deposit money to particular account:

 

let MrSmithAccount = BankingAccount()

let depositToSmithsAccount = MrSmithAccount.deposit

depositToSmithsAccount(1000)

 

 

In all It will look like code below:

 

class BankingAccount {

var balance: Double = 0.0

func deposit(amount: Double) {

balance += amount

}

}

let account = BankingAccount()

account.deposit(100) // 100 deposited

let depositor:(BankingAccount) -> (Double) ->

Void=BankingAccount.deposit

depositor(account)(100) //another 100 deposited

let a = account.balance

let MrSmithAccount = BankingAccount()

let depositToSmithsAccount = MrSmithAccount.deposit

depositToSmithsAccount(1000)

 

 

That’s it. Curried function is just function taking parameter and returning another function which takes another parameter. This trick gives way to produce new functions from existing ones.

Leave a Comment: