Professional Documents
Culture Documents
Question 1:
Answer:
● Activation Records:
○ When a subprogram is called, an activation record (AR) is created on the runtime
stack.
○ The AR stores:
■ Local variables
■ Parameters
■ Return address
■ Temporary data
○ ARs are pushed onto the stack for nested calls and popped upon return.
● Stack Allocation:
○ Local variables are allocated within the AR upon subprogram entry.
○ Deallocated automatically upon return, ensuring efficient memory management.
● Compiler Role:
○ Generates code to:
■ Allocate and deallocate ARs
■ Access local variables within ARs
■ Manage control flow between subprograms
● Recursion Support:
○ Multiple instances of ARs for a subprogram can coexist on the stack, enabling
recursion.
Example (C):
C
int factorial(int n) {
if (n == 0) {
return 1;
} else {
return n * factorial(n - 1); // Recursive call
}
}
Question 2:
Answer:
Question 3:
Answer:
● Java:
○ Uses try-catch-finally blocks for exception handling.
○ Checked exceptions (must be handled explicitly) and unchecked exceptions
(runtime errors).
○ throw keyword to raise exceptions.
● Ada:
○ Uses blocks and exception handlers for exception handling.
○ Handlers can be nested and associated with specific blocks.
○ raise keyword to raise exceptions.
● Similarities:
○ Both support:
■ Raising and propagating exceptions
■ Defining handlers for specific exception types
■ Using a finally block for guaranteed code execution
● Differences:
○ Java distinguishes between checked and unchecked exceptions.
○ Ada's exception handling is more structured and integrated with its block
structure.
Question 4:
Answer:
● Semaphores:
○ Synchronization primitives used to control access to shared resources in
multithreaded or multiprocess environments.
○ Two operations:
■ wait(): Decrements the semaphore value, blocks if already 0.
■ signal(): Increments the semaphore value, potentially unblocking a waiting
thread.
● Ensuring Mutual Exclusion:
○ Initialize a semaphore to 1 to protect a critical section.
○ Threads call wait() before entering and signal() after exiting.
● Coordinating Tasks:
○ Use semaphores to synchronize task execution and ensure proper ordering.
Example (Java):
Java
Semaphore mutex = new Semaphore(1); // Semaphore for mutual
exclusion
void criticalSection() {
mutex.acquire(); // Acquire lock
// Access shared resource
mutex.release(); // Release lock
}
Question 5a:
Answer:
2. Web Development:
● Functional languages offer robust concurrency and modularity, making them ideal for
building scalable and responsive web applications.
● Examples: Elm, Haskell, OCaml, Elixir, and Clojure in web frameworks and server-side
development.
● Functional languages handle large datasets effectively due to their ability to express
data transformations concisely and handle parallelism efficiently.
● Examples: Scala, Haskell, and F# in data processing pipelines and distributed
systems.
4. Financial Systems:
5. Embedded Systems:
● The expressiveness of functional languages makes them ideal for creating DSLs
tailored to specific problem domains.
● Examples: DSLs for web development, data analysis, financial modeling, and scientific
computing.
Question 5b:
Answer:
1. Conditional Statements:
2. Loops:
count = 0
while count < 10:
print(count)
count += 1
4. Pass Statement:
Answer:
Haskell
factorial :: Integer -> Integer
factorial 0 = 1
factorial n = n * factorial (n - 1)
● Paradigm: Focus on how to change the state of the program using statements that
manipulate variables.
● Focus: Assignments, control flow (loops, conditionals), mutable data structures.
● Examples: C, Java, Python, C++, JavaScript.
● Code Example (Java):
Java
int factorial(int n) {
if (n == 0) {
return 1;
} else {
return n * factorial(n - 1);
}
}
Key Differences:
Answer:
Basic Elements:
Prolog
parent(john, mary).
Prolog
grandparent(X, Z) :- parent(X, Y), parent(Y, Z).
● Queries: Questions posed to the Prolog interpreter to deduce information from facts
and rules.
Prolog
?- grandparent(john, Who).
Answer:
Data Abstraction: The separation of data representation from its operations, creating a
clear interface.
Design Issues:
Parameterized Abstract Data Types (ADTs): ADTs that can be customized with different
data types, promoting reusability.
Java
interface List<T> {
void add(T item);
T get(int index);
int size();
}
C++
template <typename T>
class Stack {
public:
void push(T item);
T pop();
bool isEmpty();
private:
std::vector<T> elements;
};
Definition: Multiple subprograms with the same name but different parameter lists, allowing
for flexibility in function calls based on argument types.
Example (C++):
C++
#include <iostream>
int main() {
std::cout << add(3, 5) << std::endl; // Calls int add(int,
int)
std::cout << add(3.5, 2.7) << std::endl; // Calls double
add(double, double)
}
Example (Pseudocode):
Code snippet
procedure A()
x = 10
call B()
procedure B()
print(x) // Accesses x from A's activation record (dynamic
scoping)
Mechanism:
Steps:
1. Throw an exception:
C++
throw exception_object;
2. Catch an exception:
C++
try {
// Code that might throw exceptions
} catch (exception_type e) {
// Handle the exception
}
Key Issues:
Additional Considerations:
● yield():
○ Temporarily pauses the currently executing thread, allowing other threads of the
same priority to run.
○ Doesn't guarantee immediate relinquishment of control, as it's a hint to the
scheduler.
○ Syntax: Thread.yield();
● sleep():
○ Puts the currently executing thread to sleep for a specified time in milliseconds.
○ Guarantees that the thread won't resume execution until the specified time has
elapsed.
○ Syntax: Thread.sleep(milliseconds);
● Cooperation Synchronization:
○ Semaphores can coordinate threads to work together on shared tasks.
○ Example: Producer-consumer problem, where a producer thread creates items
and a consumer thread consumes them, using a semaphore to control access to
a shared buffer.
● Competition Synchronization:
○ Semaphores can ensure exclusive access to shared resources, preventing race
conditions.
○ Example: Mutual exclusion (mutex), where only one thread can access a critical
section at a time, using a semaphore to control access.
● Dynamically Typed: Variable types are determined at runtime, not at compile time.
● Basic Data Types:
○ Numbers (int, float, complex)
○ Strings
○ Booleans (True, False)
○ None (represents the absence of a value)
● Mutable vs. Immutable Types:
○ Mutable types (lists, dictionaries) can be changed after creation.
○ Immutable types (numbers, strings, tuples) cannot be changed after creation.
Procedural Abstraction:
Python
def calculate_area(length, width):
area = length * width
return area
Data Abstraction:
Python
class
Rectangle:
def
__init__(self, length, width):
self.length = length
self.width = width
def
calculate_area(self):
Key Differences:
C++
template <typename T>
T max(T a, T b) {
return (a > b) ? a : b;
}
Java
public class Box<T> {
private T item;
public void setItem(T item) {
this.item = item;
}
public T getItem() {
return item;
}
}
● C# Name Spaces:
○ Organize code into logical groups to avoid naming conflicts.
○ Declared using the namespace keyword.
○ Example:
C#
namespace MyApplication.DataAccess {
// Classes and interfaces related to data access
}
● Ada Packages:
○ Similar concept, grouping related entities (types, subprograms, etc.).
○ Declared using the package keyword.
● Java Packages:
○ Also used for code organization and avoiding naming conflicts.
○ Declared using the package keyword.
Java:
Java
button.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
// Handle button click event
}
});
C#:
C#
button.Click += (sender, args) => {
// Handle button click event
};
Common Concepts:
● Exception: An object representing an abnormal condition or error that occurs during
program execution.
● Throwing an exception: Signaling that an error has occurred, using the throw
keyword (or equivalent).
● Catching an exception: Handling the error using try-catch blocks (or similar
constructs).
C#:
● Structure:
C#
try {
// Code that might throw exceptions
} catch (ExceptionType1 ex1) {
// Handle exception type 1
} catch (ExceptionType2 ex2) {
// Handle exception type 2
} finally {
// Code that always executes, regardless of exceptions
}
● Example:
C#
try {
int result = int.Parse("abc"); // Throws FormatException
} catch (FormatException e) {
Console.WriteLine("Invalid input format.");
} finally {
Console.WriteLine("Cleaning up resources.");
}
Java:
● Structure: Identical to C#
● Example:
Java
try {
int[] numbers = {1, 2, 3};
System.out.println(numbers[10]); // Throws
ArrayIndexOutOfBoundsException
} catch (ArrayIndexOutOfBoundsException e) {
System.out.println("Index out of bounds.");
}
Ada:
● Structure:
Ada
begin
-- Code that might raise exceptions
exception
when ExceptionType1 =>
-- Handle exception type 1
when ExceptionType2 =>
-- Handle exception type 2
end;
● Example:
Ada
declare
X : Integer;
begin
X := 10 / 0; -- Raises Constraint_Error
exception
when Constraint_Error =>
Put_Line("Division by zero.");
end;
Key Differences: