COMPUTER PROGRAMMING PARADIGM (1)
COMPUTER PROGRAMMING PARADIGM (1)
Course Outcomes
ITL303.1 Understand data abstraction and object orientation
ITL303.2 Design and implement declarative programs in functional and logic programming
languages
ITL303.3 Introduce the concepts of concurrent program execution.
Class
The building block of C++ that leads to Object-Oriented programming is a Class. It is a user-
defined data type, which holds its own data members and member functions, which can be
accessed and used by creating an instance of that class. A class is like a blueprint for an object.
For Example: Consider the Class of Cars. There may be many cars with different names and
brands but all of them will share some common properties like all of them will have 4 wheels,
Speed Limit, Mileage range, etc. So here, the Car is the class, and wheels, speed limits, and
mileage are their properties.
Object
An Object is an identifiable entity with some characteristics and behavior. An Object is an
instance of a Class. When a class is defined, no memory is allocated but when it is instantiated
(i.e. an object is created) memory is allocated.
Encapsulation
In normal terms, Encapsulation is defined as wrapping up data and information under a single
unit. In Object-Oriented Programming, Encapsulation is defined as binding together the data
and the functions that manipulate them. Consider a real-life example of encapsulation, in a
company, there are different sections like the accounts section, finance section, sales section,
etc.
Encapsulation also leads to data abstraction or data hiding. Using encapsulation also hides the
data. In the
Abstraction
Data abstraction is one of the most essential and important features of object-oriented
programming in C++. Abstraction means displaying only essential information and hiding the
details. Data abstraction refers to providing only essential information about the data to the
outside world, hiding the background details or implementation.
Polymorphism
The word polymorphism means having many forms. In simple words, we can define
polymorphism as the ability of a message to be displayed in more than one form. A person at
the same time can have different characteristics. A man at the same time is a father, a husband,
and an employee. So the same person possesses different behavior in different situations.
This is called polymorphism.
Inheritance
The capability of a class to derive properties and characteristics from another class is
called Inheritance. Inheritance is one of the most important features of Object-Oriented
Programming.
• Sub Class: The class that inherits properties from another class is called Sub class or Derived
Class.
• Super Class: The class whose properties are inherited by a sub-class is called Base Class or
Superclass.
Dynamic Binding
In dynamic binding, the code to be executed in response to the function call is decided at
runtime. C++ has virtual functions to support this. Because dynamic binding is flexible, it
avoids the drawbacks of static binding, which connected the function call and definition at
build time.
Message Passing
Objects communicate with one another by sending and receiving information. A message for
an object is a request for the execution of a procedure and therefore will invoke a function in
the receiving object that generates the desired results. Message passing involves specifying
the name of the object, the name of the function, and the information to be sent.
CODE:
ENCAPSULATION
CODE:
// Program to calculate the area of a rectangle
#include <iostream>
using namespace std;
class Rectangle {
public:
// Variables required for area calculation
int length;
int breadth;
return 0;
}
OUTPUT:
DYNAMIC INTILIZATION
CODE:
public:
// Default constructor
geeks()
{
// Dynamically initializing ptr
// using new
ptr = new int;
*ptr = 10;
}
// Driver Code
int main()
{
geeks obj1;
// Function Call
obj1.display();
return 0;
}
OUTPUT:
Single inheritance
CODE :
#include <iostream>
using namespace std;
class Account {
public:
float salary = 60000; };
class Programmer: public Account {
public:
float bonus = 5000; };
int main(void) {
Programmer p1;
cout<<"Salary: "<<p1.salary<<endl;
cout<<"Bonus: "<<p1.bonus<<endl;
return 0; }
C++ Multilevel Inheritance
CODE:
#include <iostream>
using namespace std;
class Animal {
public:
void eat() {
cout<<"Eating..."<<endl;
}
};
class Dog: public Animal
{
public:
void bark(){
cout<<"Barking..."<<endl;
}
};
class BabyDog: public Dog
{
public:
void weep() {
cout<<"Weeping...";
}
};
int main(void) {
BabyDog d1;
d1.eat();
d1.bark();
d1.weep();
return 0;
}
OUTPUT:
Multiple inheritance is the process of deriving a new class that inherits the attributes from
two or more classes.
CODE:
#include <iostream>
using namespace std;
class A
{
protected:
int a;
public:
void get_a(int n)
{
a = n;
}
};
class B
{
protected:
int b;
public:
void get_b(int n)
{
b = n;
}
};
class C : public A,public B
{
public:
void display()
{
std::cout << "The value of a is : " <<a<< std::endl;
std::cout << "The value of b is : " <<b<< std::endl;
cout<<"Addition of a and b is : "<<a+b;
} };
int main()
{
C c;
c.get_a(10);
c.get_b(20);
c.display();
return 0;
}
OUTPUT:
C++ Hybrid Inheritance
CODE:
#include <iostream>
using namespace std;
class A
{
protected:
int a;
public:
void get_a()
{
std::cout << "Enter the value of 'a' : " << std::endl;
cin>>a;
}
};
class B : public A
{
protected:
int b;
public:
void get_b()
{
std::cout << "Enter the value of 'b' : " << std::endl;
cin>>b;
}
};
class C
{
protected:
int c;
public:
void get_c()
{
std::cout << "Enter the value of c is : " << std::endl;
cin>>c;
}
};
Hierarchical inheritance is defined as the process of deriving more than one class from a base
class.
CODE:
#include <iostream>
using namespace std;
class Shape // Declaration of base class.
{
public:
int a;
int b;
void get_data(int n,int m)
{
a= n;
b = m;
}
};
class Rectangle : public Shape // inheriting Shape class
{
public:
int rect_area()
{
int result = a*b;
return result;
}
};
class Triangle : public Shape // inheriting Shape class
{
public:
int triangle_area()
{
float result = 0.5*a*b;
return result;
}
};
int main()
{
Rectangle r;
Triangle t;
int length,breadth,base,height;
std::cout << "Enter the length and breadth of a rectangle: " << std::endl;
cin>>length>>breadth;
r.get_data(length,breadth);
int m = r.rect_area();
std::cout << "Area of the rectangle is : " <<m<< std::endl;
std::cout << "Enter the base and height of the triangle: " << std::endl;
cin>>base>>height;
t.get_data(base,height);
float n = t.triangle_area();
std::cout <<"Area of the triangle is : " << n<<std::endl;
return 0;
}
Output:
EXPERIMENT NO .02
THEORY :Haskell is a statically typed, purely functional programming language known for its strong
type system, lazy evaluation, and expressive syntax. Setting up the Haskell programming environment
is the first step to start coding in Haskell. This tutorial will guide you through the installation and basic
usage of Haskell.
1. Installing Haskell
The most common way to install Haskell is by using the Haskell Platform or GHCup. Here's how to get
started with both methods:
1. Download GHCup:
o Once GHCup is installed, you can install GHC (Glasgow Haskell Compiler) and Cabal
(the build system and package manager) with:
code
5. Verify Installation:
Code
ghc --version
cabal –version
2. Setting Up a Simple Haskell Project
code
mkdir my-haskell-project
cd my-haskell-project
cabal init
code
-- Main.hs
main :: IO ()
code
cabal build
code
cabal run
You have now set up your Haskell programming environment and created a simple project. With
GHCi, you can interactively test your Haskell code, while Cabal helps you manage your projects. Start
exploring Haskell's features, and happy coding!
EXPERIMENT NO .03
AIM : Demonstarte and implement Haskell : Operators and Types
Theory :
This exercise will introduce you to Haskell’s basic operators and types. You will explore arithmetic
operators, comparison operators, logical operators, and type declarations. Let’s get started!
1. Arithmetic Operators
In Haskell, you can perform basic arithmetic operations like addition, subtraction, multiplication, and
division.
code
5+3 -- Addition
10 - 4 -- Subtraction
6*7 -- Multiplication
15 / 3 -- Division
7 `mod` 3 -- Modulus
2. Comparison Operators
haskell
Copy code
7 == 7 -- Equal to
5 /= 3 -- Not equal to
3. Logical Operators
code
In Haskell, you can define and work with different types. Here are some of the basic types:
1. Open a new file called Types.hs and write the following code:
-- Types.hs
myInt :: Int
myInt = 42
myFloat :: Float
myFloat = 3.14
myDouble :: Double
myDouble = 2.71828
myBool :: Bool
myBool = True
myChar :: Char
myChar = 'H'
code
:load Types
code
myInt
myFloat
myDouble
myBool
myChar
4. Question: Use the :t command to check the type of each variable. For example:
code
:t myInt
code
add x y = x + y
multiply x y = x * y
code
add 5 10
3. Question: What are the results of add 5 10 and multiply 2.5 4.0?
• Question: Write a brief summary of what you learned about operators and types in Haskell.
• Exercise: Create a function that takes a list of integers and returns their sum. Test your
function in GHCi.
Conclusion
You have now practiced using operators, types, and defining functions in Haskell. This exercise lays
the foundation for more advanced concepts in Haskell programming. If you have any questions or
need further clarification, feel free to ask! Happy coding!
EXPERIEMENT NO .04
AIM : Demonstrate key concepts of functional programming, including higher-order functions,
recursion, immutability, and type classes.
THEORY :
CODE:
-- Fibonacci.hs
fibonacci :: Int -> Int
fibonacci n
| n <= 0 = 0
| n == 1 = 1
| otherwise = fibonacci (n - 1) + fibonacci (n - 2)
main :: IO ()
main = do
let n = 10
putStrLn $ "Fibonacci of " ++ show n ++ " is " ++ show (fibonacci n)
OUTPUT:
This program demonstrates the use of a higher-order function by implementing a map function that
applies a function to each element in a list
Code
-- Map.hs
myMap _ [] = []
main = do
OUTPUT:
This program implements a filter function to select elements from a list based on a predicate.
Code
-- Filter.hs
myFilter _ [] = []
myFilter p (x:xs)
|px = x : myFilter p xs
| otherwise = myFilter p xs
main :: IO ()
main = do
This program calculates the factorial of a number using recursion and pattern matching.
Code
-- Factorial.hs
factorial 0 = 1
factorial n = n * factorial (n - 1)
main :: IO ()
main = do
let n = 5
OUTPUT:
5. Basic Calculator (Polymorphism and Type Classes)
This program demonstrates polymorphism using type classes to create a simple calculator.
Code
-- Calculator.hs
add = (+)
subtract = (-)
multiply = (*)
divide = div
calculate :: Int -> Int -> (Int -> Int -> Int) -> Int
main :: IO ()
main = do
let a = 10
let b = 5
Conclusion
1. Recursion: Fibonacci and factorial examples show how to use recursion for calculations.
2. Higher-Order Functions: The map and filter functions demonstrate how to pass functions as
arguments.
3. Pattern Matching: Used in the factorial function for cleaner recursive definitions.
4. Polymorphism and Type Classes: The calculator example illustrates how Haskell handles
polymorphism through type classes.
EXPERIMENT NO : 05
1. Family Relationships
CODE:
% Facts
parent(john, mary).
parent(john, bob).
parent(susan, mary).
parent(susan, bob).
parent(mary, alice).
parent(bob, charlie).
QUERY
?- sibling(mary, bob).
?- grandparent(john, alice).
OUTPUT:
2. A Simple Knowledge Base
CODE
% Facts
animal(dog).
animal(cat).
animal(bird).
mammal(dog).
mammal(cat).
can_fly(bird).
% Rules
is_mammal(X) :- mammal(X).
can_animal_fly(X) :- can_fly(X).
Queries:
?- animal(X).
?- is_mammal(dog).
% ?- can_animal_fly(bird).
CODE
% Facts
add(X, Y, Result) :- Result is X + Y.
subtract(X, Y, Result) :- Result is X - Y.
multiply(X, Y, Result) :- Result is X * Y.
divide(X, Y, Result) :- Y \= 0, Result is X / Y.
QUERY:
add(2, 3, Result).
divide(10, 2, Result).
CODE:
% Maze representation
path(a, b).
path(b, c).
path(c, d).
path(d, e).
path(a, f).
path(f, e).
% Find a path
find_path(Start, End, Path) :-
travel(Start, End, [Start], Path).
Query:
find_path(a, e, Path).
EXPERIMENT NO .06
THEORY:
1.Thread Management:
In C++, the <thread> library introduced in C++11 provides a straightforward interface for creating and
managing threads. A thread is a basic unit of CPU utilization and represents a separate path of
execution.
• Creating Threads: A thread in C++ can be created by instantiating a std::thread object and
passing a callable (function or lambda) to it.
• Joining Threads: Once a thread finishes its execution, it can be joined using the join()
method. This ensures that the main thread waits for the spawned thread to complete.
• Detaching Threads: Threads can also be detached using the detach() method, which makes
them run independently from the main thread. However, this can lead to resource
management issues if not handled carefully.
• Threads: We create two threads (t1 and t2) that run the CounterThread class, which
in turn increments the shared counter.
• Synchronization: The synchronized keyword is used in the increment() method of
the Counter class to ensure that only one thread can access this method at a time.
• Thread Management: The start() method is used to start each thread, and join()
ensures that the main thread waits until both threads have finished executing.
CODE:
class Counter {
private int count = 0;
// Synchronized method to increment the counter
public synchronized void increment() {
count++;
}
public int getCount() {
return count;
}
}
class CounterThread extends Thread {
private Counter counter;
THEORY :
Exception handling is a mechanism to handle runtime errors, ensuring the program does not crash and
can recover from unforeseen conditions.
C++ Exception Handling
In C++, exception handling is done using the try-catch blocks. A throw statement is used to signal that
an exception has occurred.
Java Exception Handling
Java handles exceptions using the same try-catch blocks, but with the built-in class Exception. Java uses
checked and unchecked exceptions, requiring some exceptions to be explicitly declared or caught.
Syntactic Differences in Exception Handling:
• In C++, any object can be thrown as an exception, while in Java, exceptions must be derived
from Throwable (typically Exception).
• Java uses a more rigid structure with checked exceptions (forcing developers to handle certain
exceptions), while C++ doesn’t impose such rules.
• C++ exceptions are caught by reference (e.g., catch (const std::exception& e)), while Java
catches exceptions as objects (e.g., catch (ArithmeticException e)).
CODE:
#include <iostream>
#include <stdexcept> // For standard exceptions
CODE:
public class Main {
public static void divide(int a, int b) throws ArithmeticException {
if (b == 0) {
throw new ArithmeticException("Division by zero error");
} else {
System.out.println("Result: " + (a / b));
}
}
OUTPUT:
EXPERIMENT NO .08
THEORY :
Garbage collection refers to the automatic management of memory, reclaiming memory that is no
longer in use. This happens differently in C++ and Java.
C++: Manual Memory Management
C++ does not have built-in garbage collection. Instead, memory management is manual, and
developers must use new and delete to allocate and free memory, respectively. Smart pointers (like
std::shared_ptr and std::unique_ptr) introduced in C++11 can help automate memory management
by providing reference counting and automatic destruction.
• Raw pointers (new and delete) require manual memory management.
• Smart pointers (std::shared_ptr, std::unique_ptr) allow automatic memory management
with scope-based destruction.
Java: Automatic Garbage Collection
In Java, the garbage collector automatically manages memory. You create objects using the new
keyword, and when an object is no longer referenced, the garbage collector reclaims the memory.
CODE:
#include <iostream>
#include <memory> // For smart pointers
class MyObject {
public:
MyObject() { std::cout << "Object created" << std::endl; }
~MyObject() { std::cout << "Object destroyed" << std::endl; }
};
int main() {
// Using raw pointers (manual memory management)
MyObject* obj = new MyObject();
delete obj; // Manual deletion
return 0;
}
OUTPUT:
CODE:
CONCLUSION:
Both C++ and Java provide robust ways to handle exceptions and memory management, but their
approaches differ significantly.
• C++ gives more control to the programmer in terms of memory management (manual
allocation and deallocation) but requires more responsibility to avoid memory leaks and
dangling pointers.
• Java simplifies memory management through automatic garbage collection, making it easier
for developers to focus on application logic without worrying about memory deallocation.
EXP NO .09
THEORY :
int factorial(int n) {
if (n == 0 || n == 1)
return 1;
else
return n * factorial(n - 1);
}
int main() {
int num = 5;
printf("Factorial of %d is %d\n", num, factorial(num));
return 0;
}
OUTPUT:
This problem checks whether a given number is prime or not, implemented in multiple paradigms
• In the procedural paradigm, the focus is on a step-by-step approach to solve the
problem.
• The is_prime function performs a specific task using loops and conditions.
CODE:
#include <stdio.h>
int is_prime(int n) {
if (n <= 1) return 0;
for (int i = 2; i <= n / 2; i++) {
if (n % i == 0)
return 0;
}
return 1;
}
int main() {
int num = 7;
if (is_prime(num))
printf("%d is a prime number\n", num);
else
printf("%d is not a prime number\n", num);
return 0;
}
OUTPUT:
• H ere, the PrimeChecker class encapsulates the behavior of checking for prime
numbers.
• The object-oriented paradigm emphasizes reusability and modularity, making it
easier to extend or modify the PrimeChecker class.
CODE:
class PrimeChecker {
public boolean isPrime(int n) {
if (n <= 1) return false;
for (int i = 2; i <= n / 2; i++) {
if (n % i == 0)
return false;
}
return true;
}
}
public class Main {
public static void main(String[] args) {
PrimeChecker checker = new PrimeChecker();
int num = 7;
if (checker.isPrime(num))
System.out.println(num + " is a prime number");
else
System.out.println(num + " is not a prime number");
}
}
OUTPUT:
EXPERIMENT NO .10
THEORY:
num = 5
print(f"Factorial of {num} is {factorial(num)}")
Query:
factorial(5, Result).
• Functional programming in Haskell focuses on pure functions without mutable state.
• The isPrime function is concise and uses list comprehensions to check if the number
is divisible by any number between 2 and n-1.
CODE:
is_prime(2).
is_prime(N) :- N > 2, \+ has_factor(N, 2).
Query: is_prime(7).