Basics of functional programming

 


Functional programming (also called FP) is a way of thinking about software construction by creating pure functions. It avoids concepts of shared state, mutable data observed in Object Oriented Programming. Functional programming is derived from the mathematical style of thinking where you define the kind of inputs that go into a function and the kind of outputs that we can expect from the function.In functional code, the output of the function depends only on the arguments that are passed. Calling the function f for the same value of x should return the same result f(x) no matter how many times you pass it. 

Functional languages emphasize on expressions and declarations rather than execution of statements. Therefore, unlike other procedures which depend on a local or global state, value output in FP depends only on the arguments passed to the function.

Functional Programming is based on Lambda Calculus: 

Lambda calculus is a framework developed by Alonzo Church to study computations with functions. It can be called the smallest programming language in the world. It gives the definition of what is computable. Anything that can be computed by lambda calculus is computable. It is equivalent to the Turing machine in its ability to compute. It provides a theoretical framework for describing functions and their evaluation. It forms the basis of almost all current functional programming languages. 

Programming Languages that support functional programming: Haskell, JavaScript, Python, Scala, Erlang, Lisp, ML, Clojure, OCaml, Common Lisp, Racket. 

Characteristics of functional programming

A functionally pure language should support the following constructs:

  • Pure functions
  • Recursion
  • Referential transparency
  • Functions are First-Class and can be Higher-Order
  • Variables are Immutable


 

Illustrating the characteristics of functional programming using python

 

Pure functions

 


These functions have two main properties: 

  • First, they always produce the same output for the same arguments irrespective of anything else. 
  • Secondly, they have no side-effects i.e. they do not modify any arguments or local/global variables or input/output streams. This  property is called immutability. The pure function’s only result is the value it returns. They are deterministic. 

 

Programs done using functional programming are easy to debug because pure functions have no side effects or hidden I/O. Pure functions also make it easier to write parallel/concurrent applications. When the code is written in this style, a smart compiler can do many things – it can parallelize the instructions, wait to evaluate results when needing them, and memorize the results since the results never change as long as the input doesn’t change. 

 

Example:

 

# example of impure function 
a = 10
def im_impure():
    global a 
    a = a+20 
    return a

print(im_impure())
# example of pure function

def pure(x,y):
    return (x+y)

print(pure(2,3))

# example of impure function
def naive_sum(*args):
    sum = 0           # pure function does not support variable assignment and manipulations
    for i in args:
        sum = sum+i 
    return sum

print(naive_sum(10,20,30,40))

# example of pure function
def pure_sum(*args):
    return sum(args)
print(pure_sum(10,20,30,40))

 

 

Recursion: 

 


There are no “for” or “while” loops in functional languages. Iteration in functional languages is implemented through recursion. Recursive functions repeatedly call themselves, until it reaches the base case. 

# sum of n-natural number using recursion
def sum(num):
    if num==0:
        return num 
    else:
        return num+sum(num-1)

sum(10)

# find n-th fibonacci term using recursion

def fib(n):
    if n==0 or n==1:
        return n
    else:
        return fib(n-1)+fib(n-2)

print(fib(10))

Reducing the usage of loops

l = list(range(10))

squared = list(map(lambda i:i**2,l))
even_number = list(filter(lambda i:i%2==0,l))
print(squared)
print(even_number)

text = "this is sample TEXT"

def func1(txt):
    return txt.upper()

def func2(txt):
    return txt.lower()

x = lambda i: func1(i)
y = lambda i: func2(i)

print(x(text))
print(y(text))

from functools import reduce
l = list(range(10))
reduce(lambda x,y:x+y,l)

Referential transparency: 

 


In functional programs variables once defined do not change their value throughout the program. Functional programs do not have assignment statements. If we have to store some value, we define new variables instead. This eliminates any chances of side effects because any variable can be replaced with its actual value at any point of execution. State of any variable is constant at any instant. 

def sum(x):
    x = x+10 # This changes the state of variable x
    print(x)


 

Functions are First-Class and can be Higher-Order: 

 


First-class functions are treated as first-class variable. The first class variables can be passed to functions as parameter, can be returned from functions or stored in data structures. Higher order functions are the functions that take other functions as arguments and they can also return functions. 

# python uses the concept of function closure to achieve this concept
def outer(a):
    def inner(b):
        return a,b
    return inner


x = outer
y = x("hello")
z = y("world")
print(z)

 

variables are Immutable: 

 


In functional programming, we can’t modify a variable after it’s been initialized. We can create new variables – but we can’t modify existing variables, and this really helps to maintain state throughout the runtime of a program. Once we create a variable and set its value, we can have full confidence knowing that the value of that variable will never change.  

 

Functional Programming vs. Object-oriented Programming

 

Functional Programming

OOP

FP uses Immutable data.

OOP uses Mutable data.

Follows Declarative Programming based Model.

Follows Imperative Programming Model.

What it focuses is on: “What you are doing. in the programme.”

What it focuses is on “How you are doing your programming.”

Supports Parallel Programming.

No supports for Parallel Programming.

Its functions have no-side effects.

Method can produce many side effects.

Flow Control is performed using function calls & function calls with recursion.

Flow control process is conducted using loops and conditional statements.

Execution order of statements is not very important.

Execution order of statements is important.

Supports both “Abstraction over Data” and “Abstraction over Behavior.”

Supports only “Abstraction over Data”.