Programming paradigms PP_Module2
Programming paradigms PP_Module2
A data type is a classification of data that specifies how data is stored and used.
• What actions can be done with that data (like adding numbers or joining text)
Programs work with data, and how easy it is to write a program depends on how well the
language’s data types match real-world needs.
Primitive data types are the basic data types provided directly by a programming language —
they aren’t built using other types. They are the building blocks used to create more complex
data types.
1. Numeric Types
➤ 1.1 Integer
Fun fact: Python can handle really big integers (long integers) that go beyond normal
hardware limits.
➤ 1.2 Floating-Point
• Most languages include two floating-point types, often called float and double.
• The float type is the standard size, usually being stored in four bytes of memory.
• The double type is provided for situations where larger fractional parts and/or a larger range
of exponents is needed.
➤ 1.3 Complex
➤ 1.4 Decimal
3. Character Types
• Characters (letters, numbers, symbols) are stored as numbers using special codes.
• Traditionally, the most commonly used coding was the 8-bit code ASCII (American
Standard Code for Information Interchange), Interchange), which uses the values 0 to 127
to code 128 different characters.
• ISO 8859-1 is another 8-bit character code, but it allows 256 different characters. Ada 95+
uses ISO 8859-1.
• Most of the languages now use Unicode. Unicode includes the characters from most of the
world’s natural languages. The first 128 characters of Unicode are identical to those of
ASCII.
• Note: Python doesn’t have a separate char type — it uses 1-character strings instead.
Character String Types
A character string type is used to store and manipulate sequences of characters (like names,
sentences, etc.).
1. Design Issues
When designing string types in a programming language, two main questions arise:
1. Should strings be primitive types (like int, float) or arrays of characters?
• Strings are stored as arrays of characters ending with a null character ('\0').
Problem: These functions are unsafe. For example, if you copy a bigger string into a smaller one,
it can cause memory overflow.
• Python: Strings are primitive and immutable, but behave like arrays for indexing
• F# and ML: Strings are immutable and have similar operations
• Perl, JavaScript, Ruby, PHP: Support pattern matching using regular expressions
4. Evaluation
• Primitive strings are easier and cleaner to use than character arrays.
• Languages should provide string types or at least a library for string operations.
• Dynamic strings are flexible but slower due to memory management needs.
5. Implementation of Character String Types
1. Linked List:
2. Array of Pointers:
o When it grows, a new bigger memory block is allocated, and data is moved.
o Faster string operations, but more complex allocation.
User-Defined Ordinal Types
An ordinal type is a data type where values can be mapped to positive integers.
For example: 1 = Monday, 2 = Tuesday, etc.
Definition:
Example (C#):
Key Points:
Design Issues:
• Can a constant appear in more than one enum? (In Ada, yes; in C++, no)
Language Features
Evaluation:
2. Subrange Types
Definition:
Example (Ada):
Key Points:
Benefits:
Drawback:
• Slight increase in code size and execution time, but worth it for safety.
3. Implementation:
• Subrange types: Implemented same as base type, but with extra range checks
Record types
What is a Record?
o Name → String
o GPA → Float
• When you want to group heterogeneous data (i.e., data of different types).
Record vs Array
Memory layout Adjacent but variable size Adjacent and same size
In C:
In Ada:
In Lua:
• You can skip some levels if it's clear what you're referring to.
• Example:
• FIRST
• FIRST OF EMPLOYEE-NAME
Implementation Details
• Fields are stored in adjacent memory, each with its own offset.
• They hold data (fields) and may also have methods (functions).
Expressions
An expression is like a small piece of code that calculates something.
For example: a + b * 2 is an expression.
Arithmetic Expressions
Arithmetic expressions in programming mimic math expressions and are used to compute values.
They include:
• Operators (like +, -, *)
• Parentheses
• Function calls
Types of operators:
1. Operator precedence
2. Operator associativity
3. Operand evaluation order
5. Operator overloading
6. Type mixing
1.1. Precedence
o Highest: ** (exponentiation)
o Middle: *, /, %
o Lowest: +, -
• Unary minus (-a) is evaluated before binary operators, but a + -b * c needs parentheses to
clarify.
1.2. Associativity
Tells which side to start when operators have same precedence.
Examples by Language:
1.3. Parentheses
• Some languages (like APL) use only parentheses for order, making expressions more
verbose.
• Example: (+ a (* b c)) = a + b * c
• ? is "then", : is "else"
When an expression has function calls or side effects, operand evaluation order becomes
important.
a + fun(a)
Examples:
int a = 5;
int fun1() {
a = 17;
return 3;
Solutions:
Overloaded Operators
What is Operator Overloading?
• Operator overloading is when a single operator symbol (like +) is used for more than
one purpose.
• Example:
When is it Okay?
o Typing mistakes (like forgetting an operand) can lead to bugs the compiler won’t
catch:
o x = a&b; // OK
o Unary: -a (negation)
o Binary: a - b (subtraction)
Issue:
• If you accidentally leave out the first operand, the compiler may not notice.
• But since both uses are mathematically related, this isn’t a big readability problem.
Languages like C++, C#, F# allow programmers to define how operators behave for custom
types.
Example:
Suppose we want this to work:
scalar * array
How it works:
Instead of writing:
Interestingly, operator overloading was one of the C++ features that was not copied into Java.
However, it did reappear in C#.
Type Conversions
What is a Type Conversion?
Type conversion means changing a value from one data type to another.
1. Widening Conversion
2. Narrowing Conversion
• Converts a larger type → smaller type.
• So, converting int → float might lose the last 1-2 digits.
Type Conversions: Implicit vs Explicit
In C/Java/C++:
(int) angle
In F# or ML:
float(sum)
Coercion in Expressions
Mixed-Mode Expressions
• Example: int * float
Compiler converts int to float before multiplication.
Language Differences:
Ada Very limited Doesn't allow mixing int and float in most cases.
C, Java, etc. Coercions allowed Even small types like byte, short get converted to int.
Example in Java:
So small types are stored in fewer bits but are converted when used in calculations.
Errors in Expressions
Even with correct type conversions, some errors can still happen during expression evaluation.
Types of Errors:
Example:
Summary Table
1. Relational Expressions
Operator Meaning
== Equal
!= Not equal
Important Notes:
• Relational operators are often overloaded (work with multiple data types like numbers,
strings, etc.).
• In languages without Boolean types, the result may not be a true Boolean value (e.g., it
could be an integer like 0 or 1).
• Ada: /=
• Lua: ~=
• Fortran: .NE.
• ML/F#: <>
Ruby:
Precedence:
2. Boolean Expressions
• Built using:
o Boolean variables
Operator Meaning
&& AND
! NOT
Precedence Differences:
Mixing Expressions:
So, we need different levels of precedence for arithmetic, relational, and Boolean operators.
C/C++ Special Cases:
Conclusion:
• Languages with a true Boolean type (not just numbers) are more readable and safe.
• Using numbers as Boolean values (like in old C) can hide errors, because any number
becomes a valid Boolean operand.
Short-Circuit Evaluation
What is Short-Circuit Evaluation?
It’s when an expression is evaluated only as much as needed to determine its result — some
parts are skipped if they’re unnecessary.
(13 * a) * (b / 13 - 1)
• If a = 0, then the whole expression is 0, no matter what (b / 13 - 1) is.
• But in most languages, arithmetic expressions are fully evaluated, even if the result is
already known.
➤ So this shortcut is not used in arithmetic.
• If a < 0, then the first part is false, and false && anything is always false.
• So the second part doesn’t need to be checked!
• This is where short-circuit evaluation is helpful and actually used.
index = 0;
index = index + 1;
• If index becomes equal to listlen, then list[index] will crash the program (out-of-range
error).
o If it’s false, it skips the second part, and avoids the error.
• So even if the first part is false, the second part is still evaluated — and that could cause
errors (like accessing out-of-bounds elements).
A side effect is when an expression changes a variable (like b++ increases b).
(a > b) || ((b++) / 3)
• If the program relies on b being updated, this can cause subtle bugs.
Language Support for Short-Circuiting:
Summary:
Feature Description
Short-circuit
Skips parts of an expression when not needed
evaluation
Does NOT work with Arithmetic expressions (they are always fully evaluated)
Use short-circuit for safety, but be careful if your code depends on side
Best practice
effects
Assignment Statements
Assignment statements let you change the value of a variable. This is key in imperative
languages like C, Java, Python, etc.
1. Simple Assignments
• Most languages use = for assignment (like x = 5).
• But = is also used in math for equality, so languages like ALGOL 60 and Ada use := for
assignment to avoid confusion.
• In Fortran and Ada, assignment can only appear as a standalone line and can assign only
one variable at a time.
2. Conditional Targets
• Example:
• You can use them with most binary operators (+, -, *, /, etc.).
5. Assignment as an Expression
• The parentheses are needed because = has lower precedence than !=.
6. Multiple Assignments
• Languages like Perl, Ruby, and Lua allow multiple assignments:
• Reassigning cost later makes a new version, the old one is hidden.
8. Mixed-Mode Assignment
• Java and C# only allow widening conversions (e.g., int → float, but not float → int).
• In functional languages, this doesn’t apply, because variables don’t change once set.
Mixed-Mode Assignment
What is Mixed-Mode Assignment?
Mixed-mode assignment happens when you assign a value of one type to a variable of another
type.
Example:
int x;
Example in C:
Ada
Example:
x : Integer;
y : Float := 5.5;
x := Integer(y); -- explicit conversion needed
Java and C#
Widening (safe):
Narrowing (unsafe):
Summary Table
Mixed-Mode
Language Coercion Allowed? Notes
Assignment?