Imperative programming vs Functional programming – a Beginner’s approach Part 6: Chaining

1. Introduction

Computer programming is about solving problems and getting things done the right way. However, as a beginner, you don’t care how you do it as long as you get it done. It works so why bother tackling it in a completely different way after all?

I thought the same way when I first stumbled upon functional programming in Swift. I knew about functional programming languages like Haskell or Scala, but I was under the impression that they are only good for research at an academic level and have no practical value of any kind. So I approached it reluctantly at first and soon asked myself how I lived without it.

The biggest challenge you face when discovering new programming paradigms is changing the way you think. This can be scary at first because you are used to doing things in a certain way and now you suddenly feel overwhelmed. It takes time and patience to get used to anything new but it’s worth doing it in the long run – being able to choose the right technique for a certain problem is a skill that any software developer should have in his toolbox.

OK, enough talking – let’s see what functional programming is all about.

2. The imperative approach

Your task for this tutorial is an easy one: compute the sum of the even elements in an array. Before diving into coding think how you would solve the problem and break it into steps. This is how I would do it:

  • create the array and populate it with default values;
  • create the sum variable and assign its initial value;
  • loop through the array and do three things for each iteration:
    • extract the current value from the array;
    • test if it’s even;
    • add it to the sum if the test succeeds;
  • print the sum to the console;

That’s it for the algorithm – let’s move on to the implementation.

3. The imperative implementation

Fire up Xcode and open a playground. Delete everything from it and add this line to kick things off:

let array = [1, 2, 3, 4, 5]

This creates the initial constant array and assigns its default values.

Note: There are many different ways of creating arrays in Swift – this is the easiest approach of all because it uses type inference to determine the array’s type – Int in this case.

Next create the sum variable and assign its initial value:

var sum = 0

This line creates a variable for the sum – it is variable because you are going to change its value soon.

Note: There are many different ways of creating variables in Swift – this is the easiest approach of all because it uses type inference to determine the variable’s type – Int in this case.

Now loop through the array with the for in control flow statement:

for value in array {

}

Note: There are many ways of looping in Swift – this is the best approach for arrays because it gives you access to the current value for each iteration.

There are two things you should do inside the for loop for each value of the array. First test if the value is even:

if value % 2 == 0 {
    
}

Note: You can also use guard instead of if and take the happy path approach instead (Download).

Then add it to the sum inside the if statement if the test succeeds:

sum += value

Note: You could also do it like this – the initial approach is shorter because it uses the addition assignment operator:

sum = sum + value

Finally, print the sum to the console:

print(sum, terminator: "")

Note: There are other ways to print to the console as well – this approach doesn’t print the newline “\n” character in the playground.

That’s it – time for your next challenge: calculate the product of the odd elements in an array.

4. The imperative implementation revisited

First create the product variable and assign its initial value:

var product = 1

Next loop through the array:

for value in array {

}   

Now test if the value is odd and multiply the product by the value if the test succeeds:

if value % 2 == 1 {
        
    product *= value

}

Note: You could also do the multiplication like this – the initial approach is shorter because it uses the multiplication assignment operator:

product = product * value

Finally, print the product to the console:

print(product, terminator: "")

That’s it – let’s compare the two implementations.

5. The imperative implementation analysed

Both implementations are similar:

  • create the result variable and assign its initial value;
  • loop through the array;
  • extract the current value;
  • test the value and modify the result with it if the test succeeds;
  • print the result to the console;

There are only three major differences between them – the result’s initial value is either 0 or 1, the remainder of the value’s division by 2 is either 0 or 1 and the operation’s type is either addition or multiplication.

Note: You could refactor the whole thing in two ways:

Both approaches avoid code redundancy and respect the DRY (don’t repeat yourself) principle, but they don’t deal with the boilerplate code that is common for both implementations. Functional programming to the rescue!

6. The functional approach

Functional programming is about focusing only on what changes and not caring about what stays the same. The only thing that varies between the two previous implementations is the logic that filters each value in the array and reduces the filtered elements to a certain value, so this is the only thing you have to worry about.

The filter and reduce functions do exactly this: create an array from the elements of another array that respect a certain condition and compute a value from the elements of an array based on a certain type of operation.

Enough theory – let’s see the filter and reduce functions in action!

7. The functional implementation

Add this line to the playground to get started:

let evenfArray = array.filter{$0 % 2 == 0}

The filter function uses a closure – a fancy word for anonymous function – as its parameter. The closure’s body is the condition that filters the array’s elements and the closure’s argument – $0 – is the array’s current value.

Note: The closure’s body can be written in many other ways in Swift – this is the simplest approach of all because it uses trailing closure syntax and shorthand argument names. You can read more about the filter function here.

Next reduce the previously created array:

let sumf = evenfArray.reduce(0, combine: +)

The reduce function has two parameters – the initial value and the operation’s type.

Note: The function’s prototype can be written in many other ways in Swift – this is the simplest approach of all because it uses default operators for its arguments. You can read more about the reduce function here.

Now print the sum to the console:

print(sumf, terminator: "")

That’s it! Let’s use the filter and reduce functions some more.

8. The functional implementation revisited

First filter the odd elements in the array:

let oddfArray = array.filter{$0 % 2 == 1}

Next reduce the previously created array:

let productf = oddfArray.reduce(1, combine: *)

Now print the product to the console:

print(productf, terminator: "")

That’s it – let’s compare the two implementations.

9. The functional implementation analysed

Both implementations are similar – filter and reduce the array – no more boilerplate code. That’s great but you can do even better by chaining the two operations together.

Note: You could refactor the whole thing by encapsulating the algorithm in a function of its own to avoid code redundancy and respect the DRY principle (Download).

Enough theory – let’s see functional chaining in action!

10 The functional chaining implementation

Add this line to the playground to get started:

let sumfc = array.filter{$0 % 2 == 0}.reduce(0, combine: +)

This line combines the two steps from the functional implementation into a single one and gets rid of the intermediate constant.

Now print the sum to the console:

print(sumfc, terminator: "")

That’s it – it can’t get any simpler than that! Let’s use functional chaining some more.

11. The functional chaining implementation revisited

Calculate the product of the odd elements in an array:

let productfc = array.filter{$0 % 2 == 1}.reduce(1, combine: *)

Now print the product to the console:

print(productfc, terminator: "")

That’s it – let’s compare the two implementations.

12. The functional chaining implementation analysed

Both implementations are similar – combine the steps from the functional implementation into a single one – short and sweet.

Note: You could refactor the whole thing by encapsulating the algorithm in a function of its own to avoid code redundancy and respect the DRY principle (Download).

13. Imperative vs functional comparison

Imperative advantages:

  • clear steps
  • easy to understand

Imperative disadvantages:

  • boilerplate code

Functional advantages:

  • no boilerplate code
  • short and sweet

Functional disadvantages:

  • difficult to understand

14. Conclusion

Both paradigms have their pros and cons – feel free to try them both and choose the one that suits you best. Happy coding! 🙂

Note: All the code in this tutorial was tested with a playground in Xcode 7.1 and Swift 2.1 (Download).

Advertisements
Posted in Functional programming

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Enter your email address to receive notifications of new posts by email.

Simple Programmer
%d bloggers like this: