What are programming paradigms?

Overview

A programming paradigm refers to the pattern that a program code follows. It can be thought of as the style of programming. Some languages enforce a paradigm on us when we use those languages, while others allow us to program in whichever paradigm we wish. In this article, we're going to take a look at a few common programming paradigms. Although there are several other paradigms than the ones listed below, we're going to focus on the following five paradigms:

  • Imperative
  • Procedural
  • Object-oriented
  • Functional
  • Declarative

Before delving into explanations of these different paradigms, let's briefly discuss why we need to know them in the first place. We care about programming paradigms because there are often multiple solutions to the same problem. Often, we may even use different languages to solve a problem. Knowing about different programming paradigms can help us decide the best solution and the most suitable language for the solution to the problem at hand and increase our work efficiency.

Let's discuss the five paradigms listed above.

Imperative paradigm

In the imperative paradigm, we write statements that describe how to solve our problem step by step. A statement here refers to some action to be carried out. One thing peculiar to the imperative paradigm is that every statement changes the program’s state. A typical example of an imperative language is C. Let’s say we want to calculate the area of a circle. We know that the area of a circle is given by ππ×radius2radius^2.

When we input a value for the radius in the code below, it will compute the area of the corresponding circle.

PI = 3.14
radius = int(input())
area = PI*radius**2
print("Area of the circle:",area)

Enter the input below

In the code above, we enter the radius of a circle in the input box. We then compute the area of the circle and print the result.

Every statement above changes the program’s state.

  • In the first line, we declare the value of PI.
  • Next, we read some value from the user. In this step, the state of the program is tilted toward reading from the standard input
  • We then compute the area of the circle and print the area of the circle. In this step, the program state is toward the standard output.

Procedural paradigm

The procedural paradigm is a subset of the imperative programming paradigm, so it has all its features. In this paradigm, the program instructions are divided into subroutines or procedures. These are simply blocks of code to carry out specific tasks. This paradigm encourages modularity, that is, dividing solutions into smaller blocks, each of which does one thing. A procedure may call another procedure in itself. This paradigm also encourages reusability. The C language is a typical example of a language that follows the imperative procedural paradigm.

The following is an example of code that follows the procedural paradigm:

/*
This code contains functions not defined anywhere
and thus is not executable. This is for illustration purposes.
*/
const PI = 3.14;
function readUserInput() {
// read user input from keyboard for example
return userInput;
}
function computeArea() {
const radius = readUserInput();
const area = PI * (radius * radius);
print(area);
}
function main() {
computeArea();
}
// more operations...

In the code above, we first define a value for the constant PI. We then define the function readUserInput() to read input from the user (radius of the circle) and another function computeArea() to compute the area of the circle.

We then have the main function where we call the computeArea() function.

Object-oriented paradigm (OOP)

This is another form of the imperative paradigm. In OOP, everything is considered an object. Each object holds some information and methods/procedures to mutate/modify its data. This paradigm is very popular nowadays. In OOP, we define classes/blueprints that can then make the basis for any type of object in our code. Some good examples of object-oriented languages include Java, Python3, C++, and so on.

Declarative paradigm

In this paradigm, the program is written to describe what results are expected from the program without explicitly telling the computer how to carry out the task.

Any style that is non-imperative is said to be declarative.

A typical example of a language following this style is SQL. It allows us to specify what results we want, but the inner workings of the system executing it are not our concern. A database may decide to store data in the form of a hierarchical structure while another may store it in tables. Regardless of the way the database is designed, it will still execute our SQL code even if the way it does it is different from what we'd expect based on the database design.

SELECT count() FROM Africa WHERE area >= 1000000

The SQL code above will look into a table named Africa and count the number of countries having a surface area of 1 million and above.

Functional paradigm

This is a form of declarative paradigm. With this paradigm, we can do many things with our functions, including assigning them to variables, passing them as arguments to other functions, and having other functions return them.

Functions are central to this paradigm. Some examples of functional programming languages include Lisp and Haskell, while other languages like JavaScript, Python, and many others also support this programming style. In this paradigm, we also have the concept of pure functions and impure functions. Pure functions are simply those that cannot modify an external variable, change the program’s state or read or write values from and to a user. For example, let's take a look at the computeArea() function that we saw earlier in this Answer:

// impure function
function computeArea() {
const radius = readUserInput();
const area = PI * (radius * radius);
print(area);
}

We see that it reads a value from the user and then prints its result. This function is considered impure because it changes the program’s state.

A pure function implementation would look like it does in the following code:

// pure function
function computeArea(radius) {
const area = PI * (radius * radius);
return area;
}

Here, the function does not read or write. The radius is passed to the function as an argument, and it returns the area of the circle. The function does all this without mutating any external value or changing the program’s state.

A function is also considered impure if it modifies the value of an external variable, as in the example below:

let area;
// impure function
function computeArea(radius) {
// changes the value of area which is an external variable to the function
area = PI * (radius * radius);
}

Free Resources