Programming paradigms are the lenses through which developers view and structure their code. Each paradigm offers a distinct approach to problem-solving, catering to diverse needs and fostering creativity. In this article, we'll explore several programming paradigms and provide sample code snippets to illustrate their unique characteristics.

1. Imperative Programming

Imperative programming focuses on describing how a program operates by providing explicit instructions. Classic examples include languages like C and Fortran, where developers specify the sequence of steps to achieve a particular outcome.

Example (C):

#include <stdio.h>

int main() {
    int sum = 0;

    for (int i = 1; i <= 5; ++i) {
        sum += i;
    }

    printf("Sum: %d\n", sum);
    return 0;
}

2. Declarative Programming

In contrast, declarative programming emphasizes what a program should accomplish without specifying how to achieve it. SQL (Structured Query Language) is a prime example, where developers declare the desired outcome (query results) without detailing the step-by-step process.

Example (SQL):

-- Declarative SQL query to retrieve user information
SELECT username, email FROM users WHERE country = 'USA';

3. Procedural Programming

Procedural programming organizes code into procedures or functions. Languages like C, Python and Pascal follow this paradigm, breaking down the program into smaller, manageable units.

Example (Python):

def calculate_sum():
    sum = 0

    for i in range(1, 6):
        sum += i

    print("Sum:", sum)

calculate_sum()

4. Object-Oriented Programming (OOP)

Object-Oriented Programming (OOP) models programs as interacting objects, encapsulating data and behavior. Java, Python, and C++ are prominent languages that follow this paradigm, promoting modularity and code reusability.

Example (Java):

public class Circle {
    private double radius;

    public Circle(double radius) {
        this.radius = radius;
    }

    public double calculateArea() {
        return Math.PI * radius * radius;
    }
}

// Example usage
Circle myCircle = new Circle(5.0);
double area = myCircle.calculateArea();

5. Functional Programming

Functional programming treats computation as the evaluation of mathematical functions and avoids changing state or mutable data. Haskell, Lisp, and Scala exemplify functional programming languages, promoting immutability and higher-order functions.

Example (Haskell):

-- Functional programming example in Haskell
sumUpTo :: Int -> Int
sumUpTo n = foldr (+) 0 [1..n]

main :: IO ()
main = do
    let result = sumUpTo 5
    putStrLn $ "Sum: " ++ show result

6. Logic Programming

Logic programming is based on formal logic, where programs consist of rules and facts. Prolog is a classic example, allowing developers to express relationships and rules to derive logical conclusions.

Example (Prolog):

% Logic programming example in Prolog
parent(john, bob).
parent(jane, bob).

sibling(X, Y) :- parent(Z, X), parent(Z, Y), X \= Y.

% Query: Are John and Jane siblings?
% Query Result: true
?- sibling(john, jane).

7. Event-Driven Programming

Event-driven programming responds to events, such as user actions or system notifications. JavaScript, especially in web development, and Visual Basic are examples of languages where code execution is triggered by specific events.

Example (JavaScript):

// Event-driven programming in JavaScript
document.getElementById('myButton').addEventListener('click', function() {
    alert('Button clicked!');
});

8. Aspect-Oriented Programming (AOP)

Aspect-Oriented Programming (AOP) separates cross-cutting concerns like logging or security from the main business logic. AspectJ is a popular language extension that facilitates AOP by modularizing cross-cutting concerns.

Example (AspectJ):

// Aspect-oriented programming example using AspectJ
aspect LoggingAspect {
    pointcut loggableMethods(): execution(* MyService.*(..));

    before(): loggableMethods() {
        System.out.println("Logging: Method called");
    }
}

class MyService {
    public void doSomething() {
        System.out.println("Doing something...");
    }
}

9. Parallel Programming

Parallel programming focuses on executing multiple processes or tasks simultaneously to improve performance. MPI (Message Passing Interface) with languages like C or Fortran, as well as OpenMP, enable developers to harness parallel computing capabilities.

Example (MPI in C):

#include <stdio.h>
#include <mpi.h>

int main() {
    MPI_Init(NULL, NULL);

    int rank;
    MPI_Comm_rank(MPI_COMM_WORLD, &rank);

    printf("Hello from process %d\n", rank);

    MPI_Finalize();
    return 0;
}

10. Concurrent Programming

Concurrent programming handles multiple tasks that make progress in overlapping time intervals. Erlang and Go are examples of languages designed to simplify concurrent programming, providing features for managing concurrent processes.

Example (Erlang):

% Concurrent programming example in Erlang
-module(my_module).
-export([start/0, worker/1]).

start() ->
    Pid = spawn(my_module, worker, [1]),
    io:format("Main process spawned worker with Pid ~p~n", [Pid]).

worker(Number) ->
    io:format("Worker ~p is processing ~p~n", [self(), Number]).

11. Meta-programming

Meta-programming involves writing programs that manipulate other programs or treat them as data. Lisp (Common Lisp) and Python (with metaclasses) offer meta-programming capabilities, enabling developers to generate or modify code dynamically.

Example (Python with Metaclasses):

# Meta-programming example in Python using metaclasses
class MyMeta(type):
    def __new__(cls, name, bases, dct):
        # Modify or analyze the class during creation
        dct['modified_attribute'] = 'This attribute is modified'
        return super().__new__(cls, name, bases, dct)

class MyClass(metaclass=MyMeta):
    original_attribute = 'This is an original attribute'

# Example usage
obj = MyClass()
print(obj.original_attribute)
print(obj.modified_attribute)

In conclusion, embracing various programming paradigms enhances a developer's toolkit, enabling them to choose the right approach for each task. By understanding these paradigms and exploring sample code snippets, programmers can elevate their problem-solving skills and create more robust and flexible solutions.