Functional vs. Imperative Programming

2 major programming paradigms


23 Sep 2017 View Comments
#functional #imperative #programming #computer #paradigms #scala

Recently, I have been coding functional programming with Scala a bit. Then I questioned myself for the difference between functional and imperative programming paradigms, which are probably the two most common programming paradigm these days. These 2 programming paradigms are very different to each other which doesn’t quite mean that they are opposite to each other. However, it is really important to understand the fundamental differences between them. I would consider myself as an ‘imperative’-style coder. I favor the code written in a series of instructions with modified state of arrays/variables in between (as known as side effects). Coding in this fashion makes the most sense out of me. However, functional programming has lots of merits compared to Imperative. Let’s take a dive.

Functional Programming (FP)

Functional programming is born to solve the problems by introducing purely functional approaches. Functional programming offers anonymous types and lambda expressions which enable to be much shorter and expressive through functional programming. However, just offering these merits do not come close to meet the requirement of the functional programming. In functional programming approach, the focus is on the set of functions to be executed. There is a concrete input to each function, then those functions always return something. This is why functional programming does not have a “void” type because that has no meaning in functional programming. Also, the loop is kind of misleading because in the functional programming loop is not built in “for” or “while”. It’s built around “map”, “fold”, or “recursion”. Let me show an example code in Scala for a better understanding. Actually similar code to below tripped me for like an hour trying to understand what is going on:

object testApp extends App {
    def findMinor(group: Array[String]): Boolean = {
        for (name <- group) {
            if (name equals "John") {
                true
            }
        }
        false
    }

    val input = Array("Mary", "Calvin", "John")
    if(findMinor(input)) {
        println("Minor")
    } else {
        println("Not Minor")
    }
}

What do you think above code will output? It prints “Not Minor” because the loop basically acknowledged the statement but did not return the true. We could use explicit return to fix the problem. However, I do not think that is what the functional programming expects. Rather we could re-write this functionally much simpler: input.contains(“John”). Perhaps the example wasn’t satisfying enough to fundamentally visualize the what functional programming actually mean. Let me give you another example also written in Scala:

Functional approach:

def increment(a):
    return a + 1

Not Functional approach:

    var a = 0
    def increment(): Unit = {
        a += 1
    }

In functional programming, you need to think about one thing. Basically, it shouldn’t have any “side effects”. The functions don’t rely on data outside the current function, and it doesn’t change data that exists outside the current function. This basically sums up what the functional programming really is to be. Then there are features that follow such as Immutable data, first-class functions, mapping, reducing, pipelining, recursing, currying and the use of higher-order functions. Then there are more features supported in the Functional programming such as parallelization, lazy evaluation, determinism, anonymous types, and lambda expressions. These are really advantageous properties of functional programs. Anyways that being said, I wouldn’t categorize even Scala to be a purely functional program. However, the language has many properties that functional programming normally offers.

Imperative Programming (IP)

In contrast, most mainstream languages, including the object-oriented programming (OOP) languages such as C#, Python, C++, and Java, were designed to primarily support imperative (procedural) programming. Honestly, almost everything we see in real life is done in imperative ways. Therefore we could probably say that we are quite used to imperative ways of handling things. As an example, take a look at any cooking recipes. They are written in a sequence of steps like:

  1. pour x amount of water
  2. place pasta in the water
  3. … etc.
  4. eat

They consist of a set of instructions to be done procedurally. Aside from this specific trait (set of instructions), the imperative programming is actually all about side effects. Like I already mentioned above, a side effect is when a procedure changes a variable from outside its scope. We can straight dive into an example. In imperative programming, below occurs quite often actually:

class BankAccount {
    private int balance;
    private String accNum;
    public BankAccount(String a) {
        accNum = a;
        balance = 0;
    }
    public void deposit(int amount) {
        balance = balance + amount; 
    }
    public int getBalance() {
        return balance;
    }
}

class BankClient {
    private BankAccount bk1 = new BankAccount(a123);
    ...
    public void cutDebt(int m) {
        int am1 = bk1.getBalance();
        if (am1 < 0)
            bk1.deposit(m);wh
    }
}

This is a typical example of an object being mutated. Take a look at deposit function, it adds amount into the balance. Typically with void functions in languages like Java, it usually modifies the value of one of the object’s attributes. In a purely functional programming, the mutator like deposit functions could actually return a new object with the new balance, which in that case balance could stay immutable. You may think it is such a waste to create a new object each time, but there is good memory handling done in functional programming languages which handles this (such as garbage collection, an idea of appending, etc). With Imperative programming, it is quite flexible in terms of how variables can be mutated (side effect). So optimizer probably struggle to optimize the code with all the mutations(side effects), let me show an example of what I mean:

Imperative:

int y = 2;
int double(x){ return x * y; }
int y = 2;
int double(x){ return x * (y++); }

Functional:

double x = 2 * x

As you can see with functional, it is to very clear, always “times 2”. With Imperative, compilers do not know how much times this “x” is going to be. So there is always a slight optimization benefit with the functional approach for such reasons. They are meant to be simpler in this sense if you use them the way it should be.

Share this post

Me

I am a passionate software developer working in Downtown, Vancouver. I strongly believe in art of algorithms and together with it to write clean and efficient software to build awesome products. If you would like to connect with me, choose one from below options :) You can also send me an email at