0% found this document useful (0 votes)
6 views

Programming paradigms PP_Module2

The document provides an overview of data types in programming, focusing on primitive data types such as numeric, boolean, character, and string types, as well as user-defined ordinal types like enums and subranges. It discusses the importance of data types in programming, how they affect program design, and the operations associated with strings and records. Additionally, it covers expressions, operator precedence, and operator overloading, emphasizing their role in programming language design.

Uploaded by

aashh127
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
6 views

Programming paradigms PP_Module2

The document provides an overview of data types in programming, focusing on primitive data types such as numeric, boolean, character, and string types, as well as user-defined ordinal types like enums and subranges. It discusses the importance of data types in programming, how they affect program design, and the operations associated with strings and records. Additionally, it covers expressions, operator precedence, and operator overloading, emphasizing their role in programming language design.

Uploaded by

aashh127
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 33

Data Type

A data type is a classification of data that specifies how data is stored and used.

A data type is a way to define:


• What kind of data can be stored (like numbers, text, etc.)

• 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


What are Primitive Data Types?

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

• Integers = whole numbers (no decimals).

• Most programming languages offer multiple sizes of integers:


o Java: byte, short, int, long

o C++ / C#: Also have unsigned integers (no negative values).

• Stored as binary (1s and 0s) in the computer.


• Negative integers are stored using methods like:

o Twos-complement (most common, good for arithmetic)

o Ones-complement (rare, has two versions of zero)

o Sign-magnitude (less efficient for math)

Fun fact: Python can handle really big integers (long integers) that go beyond normal
hardware limits.
➤ 1.2 Floating-Point

• Used for decimal (real) numbers like 3.14 or 0.1.


• On most computers, floating-point numbers are stored in binary.

• But, These are approximations — not always accurate.

o Example: 0.1 can’t be exactly stored in binary.

• Most systems follow IEEE Standard 754.

• 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

• Complex numbers have a real part and an imaginary part.

o Example in Python: (7 + 3j)

• Used in fields like science and engineering.

• Supported in Fortran, Python, etc.

➤ 1.4 Decimal

• Good for exact decimal numbers, like in business or finance.

• Can represent values like 0.1 exactly (unlike floating-point).

• Example languages: COBOL, C#, F#

• Stored using BCD (Binary Coded Decimal):

o Each digit is stored separately (like text).

o Uses more memory, but avoids rounding errors.


2. Boolean Types

• Very simple type: just two values – true or false.

• Used for decision-making (conditions, switches, flags).

• Introduced in ALGOL 60.


• Most languages now have them, but early C didn’t (used 0 and 1 instead).

• Stored in 1 byte, even though 1 bit would be enough (for efficiency).

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.

• First major language to use Unicode: Java

• Other languages using Unicode: JavaScript, Python, Perl, C#, F#

• 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?

2. Should strings have a fixed length or change dynamically during execution?

2. Strings and Their Operations

Common operations on strings:

• Assignment (e.g., str1 = str2)

• Concatenation (joining, e.g., str1 + str2)


• Substring reference (access part of the string, like str[0:3])

• Comparison (check if two strings are equal or which is greater)

• Pattern Matching (find specific patterns, like searching emails or dates)

String Storage in C/C++

• Strings are stored as arrays of characters ending with a null character ('\0').

• Example: "apple" is stored as ['a', 'p', 'p', 'l', 'e', '\0'].

Common C/C++ string functions:

• strcpy – copies a string


• strcat – joins two strings

• strcmp – compares two strings

• strlen – gets the string length (excluding the null character)

Problem: These functions are unsafe. For example, if you copy a bigger string into a smaller one,
it can cause memory overflow.

Safer Option in C++:


Use the string class from the standard library (instead of char arrays).
Strings in Other Languages:

• Java: String (immutable), StringBuffer (mutable)

• C# and Ruby: Similar to Java

• 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

Example of Pattern Matching:

• /[A-Za-z][A-Za-z\d]+/ → matches names (start with letter, followed by letters/digits)

• /\d+\.?\d*|\.\d+/ → matches numeric values like 123, 123.45, .45

3. String Length Options

There are 3 ways to manage string lengths:


1. Static Length Strings:

o Fixed length, decided at creation.

o Used in Java's String, Python, C#, Ruby.

2. Limited Dynamic Length Strings:

o Can grow or shrink up to a maximum limit.

o Used in C/C++ (with null character to indicate end).

3. Dynamic Length Strings:


o Can grow/shrink without limit.

o Found in JavaScript, Perl, C++ stdlib.

o Needs extra memory management.

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

• Hardware support is rare; usually done by software.

• A descriptor is a data structure that stores information (metadata) about a variable or


data type — in this case, a string.
• You can think of a descriptor as a "summary card" for a variable. Instead of just holding
the value, it also tells you what the value is, how big it is, and where it is stored.

Storage Management Techniques for Dynamic Strings:

1. Linked List:

o Each character stored separately with a pointer.


o Easy to grow but slow and uses more memory.

2. Array of Pointers:

o Each character stored in heap, pointers managed in array.

o Faster than linked list but still uses extra memory.

3. Contiguous Storage (Common):

o Whole string stored together in memory.

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.

User-defined ordinal types are mainly of two types:

1. Enumeration Types (Enums)

Definition:

An enumeration type is a collection of named constants defined by the programmer.

Example (C#):

Here, Mon = 0, Tue = 1, and so on (by default).

Key Points:

• Used to improve readability and reliability.


• Values can be implicitly (default) or explicitly assigned.

o Example: enum Color { Red = 1, Blue = 10 };

• Helps avoid invalid operations like adding days together.


• Prevents invalid values from being assigned.

Design Issues:

• Can a constant appear in more than one enum? (In Ada, yes; in C++, no)

• Can enum be converted to integers? (Yes in C/C++, not in Java or C#)


• Can other types be assigned to enum? (Mostly not allowed in safe languages)
Language Support:

Language Features

C/C++ Enum treated as int (less safe)

Java (since 5.0) Enum is a class; supports fields & methods

C# Enum not coerced to int; safer

Ada Allows overloaded literals, no implicit coercion

ML/F# Similar to enums using datatype/type keywords

Python, JS, PHP No built-in enum support

Evaluation:

• Improves readability (e.g., Mon vs 0)

• Increases reliability (invalid assignments are blocked)

• Safer in languages like Java, C#, Ada

2. Subrange Types

Definition:

A subrange type is a subset (contiguous range) of an existing ordinal type.

Example (Ada):

subtype Index is Integer range 1..100;

subtype Weekdays is Days range Mon..Fri;

Key Points:

• Restricts values to a specific range

• Helps in loop variables and array indices

• Ensures run-time range checking

Benefits:

• Improves readability (shows valid value range)


• Increases reliability by catching out-of-range errors

• Compiler inserts range-checking code

Drawback:

• Slight increase in code size and execution time, but worth it for safety.

3. Implementation:

• Enums: Implemented using integers

• Subrange types: Implemented same as base type, but with extra range checks
Record types
What is a Record?

• A record is a collection of related data with different types.

• Example: A student record can have:

o Name → String

o Student Number → Integer

o GPA → Float

Why Use Records?

• When you want to group heterogeneous data (i.e., data of different types).

• Keeps related data organized and accessible.

Record vs Array

Feature Record Array

Type of data Different types (heterogeneous) Same type (homogeneous)

Access method By field name By index

Memory layout Adjacent but variable size Adjacent and same size

Order important? Not always Yes, index matters

Languages that Support Records

• C, C++, C#: use struct

• Ada: uses record keyword

• COBOL: uses hierarchical level numbers

• Python, Ruby, Lua: use hashes or dictionaries


• Java, C#: use classes or data classes
Syntax Examples

In C:

In Ada:

In Lua:

Accessing Record Fields

• Dot Notation (most languages):


• COBOL Style:

• Lua alternate syntax:

Elliptical References (COBOL only)

• You can skip some levels if it's clear what you're referring to.

• Example:

• FIRST
• FIRST OF EMPLOYEE-NAME

All refer to the same field if unambiguous.

Implementation Details

• Fields are stored in adjacent memory, each with its own offset.

• Offsets help the program locate fields quickly.


• Unlike arrays, no indexing — just fixed memory positions for each field.

Record vs Object (OOP)

• In OOP languages, classes often serve the role of records.

• 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 +, -, *)

• Operands (like variables or numbers)

• Parentheses

• Function calls

Types of operators:

• Unary: one operand (e.g., -a)


• Binary: two operands (e.g., a + b)

• Ternary: three operands (e.g., conditional expression ? :)

Main design issues:

1. Operator precedence

2. Operator associativity
3. Operand evaluation order

4. Side effects during operand evaluation

5. Operator overloading
6. Type mixing

1. Operator Evaluation Order

1.1. Precedence

Determines which operator is evaluated first.


• Example: a + b * c → b * c first due to higher precedence of *
• Typical 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.

• Left-to-right: most common (e.g., a - b + c)


• Right-to-left: used for exponentiation in some languages (a ** b ** c is a ** (b ** c))

Examples by Language:

• C-based: left-to-right for most, right-to-left for unary ops

• Ruby: left-to-right generally, ** is right-to-left

• Ada: exponentiation is non-associative (must use parentheses)

1.3. Parentheses

Parentheses override precedence/associativity.

• Example: (a + b) * c → add first, then multiply

• Some languages (like APL) use only parentheses for order, making expressions more
verbose.

1.4. Ruby Expressions

In Ruby, all operators are methods.

• Example: a + b → calls + method of a


• This allows operator overloading (defining custom behavior for operators)
1.5. Expressions in LISP

In LISP, everything is a function call, written prefix-style:

• Example: (+ a (* b c)) = a + b * c

1.6. Conditional Expressions

Used to write concise if-else logic:

average = (count == 0) ? 0 : sum / count;

• ? is "then", : is "else"

• Common in C, JavaScript, Ruby, Perl

2. Operand Evaluation Order

When an expression has function calls or side effects, operand evaluation order becomes
important.

2.1 Side Effects


A side effect is when a function modifies a variable, like:

a + fun(a)

• If fun(a) changes a, result depends on which operand is evaluated first

Examples:

int a = 5;

int fun1() {

a = 17;
return 3;

a = a + fun1(); // Result depends on which is evaluated first

Solutions:

• Disallow side effects in functions (used in functional programming)


• Fix evaluation order (like Java does: left to right)
• But... fixed order can prevent compiler optimizations

2.2 Referential Transparency

A function is referentially transparent if:

• It has no side effects


• It always returns the same result for the same input

Why it's good:

• Easier to understand, reason about, and optimize

Overloaded Operators
What is Operator Overloading?

• Operator overloading is when a single operator symbol (like +) is used for more than
one purpose.
• Example:

o + is used for both integer addition and floating-point addition.

o In Java, + is also used for string concatenation ("Hello" + "World" =


"HelloWorld").

When is it Okay?

• It's generally okay to overload operators as long as:

o The code remains easy to read.

o The meaning of operations stays clear and consistent.


o The code doesn’t become confusing or error-prone.
Problems with Overloading – Example: Ampersand & in C++

In C++, the ampersand (&) does two different things:

1. Binary & → Bitwise AND operation


Example: x = a & b;
Combines bits of a and b.

2. Unary & → Address-of operator


Example: x = &y;
Stores the memory address of y in x.

What’s the problem?

• These two uses are completely unrelated, so:


o Readability suffers — hard to guess what & is doing without context.

o Typing mistakes (like forgetting an operand) can lead to bugs the compiler won’t
catch:

o x = a&b; // OK

o x = &b; // Typo, but maybe treated as "address-of" instead of error

The Minus - Operator Problem

• The - operator is often overloaded as both unary and binary:

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.

User-Defined Operator Overloading

Languages like C++, C#, F# allow programmers to define how operators behave for custom
types.

Example:
Suppose we want this to work:
scalar * array

We can define * to mean "multiply each array element by scalar".

How it works:

• You write a function for the * operator.


• The compiler chooses the correct * version based on operand types.

Benefits of User-Defined Operator Overloading

If used properly, it can make code easier to read.

Example: Matrix Operations

Instead of writing:

MatrixAdd(MatrixMult(A, B), MatrixMult(C, D))

You can just write:


A*B+C*D

Looks cleaner, easier to understand.

Problems with User-Defined Overloading

1. You could define + to mean multiplication, which is confusing.

2. A reader won’t know what an operator means unless they:

o Check the types of operands.


o Look up the definition, which might be in another file.

3. In large software projects:

o If different teams define the same operator differently, it causes conflicts.

o You need to standardize the meanings before combining modules.

Operators You Can’t Overload in C++

• . (member access operator)


• :: (scope resolution operator)
These are built-in and cannot be changed.

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.

There are two kinds:

1. Widening Conversion

• Converts a smaller type → larger type.

• Safe most of the time.


• Example: int → float
(An int can safely fit inside a float.)

2. Narrowing Conversion
• Converts a larger type → smaller type.

• Not always safe — might lose data!

• Example: double → float, or float → int


(Some values may get cut off or changed.)

Example: 1.3E25 (a huge float) → int


The result might be meaningless because int can't handle that big of a number.

Widening Isn’t Always Perfect

Even though widening keeps value size, it may reduce precision.


• Example:

o int (32 bits) → about 9 digits


o float (32 bits) → about 7 digits

• So, converting int → float might lose the last 1-2 digits.
Type Conversions: Implicit vs Explicit

1. Implicit Conversion (Coercion)

• Done automatically by the compiler.


• Common in mixed-mode expressions (when operands have different types).

• Also called coercion.

Example: int + float → the int is coerced to float.

2. Explicit Conversion (Cast)

• Done by the programmer using a cast.

• Syntax differs by language.

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:

Language Coercion Support Notes

Java Yes Implicit conversion allowed.

Ada Very limited Doesn't allow mixing int and float in most cases.

ML, F# No coercion You must cast explicitly.

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:

1. Overflow – Result is too big to fit in memory.

2. Underflow – Result is too small to be represented.

3. Division by Zero – Mathematically not allowed.

These are called run-time errors or exceptions.

Example:

int x = 10 / 0; // Runtime error: division by zero


Languages can include features to detect and handle these errors.

Summary Table

Concept Meaning Example

Widening Conversion Small → Big type int → float

Narrowing Conversion Big → Small type double → int

Coercion (Implicit) Compiler converts int + float (int → float)

Cast (Explicit) Programmer converts (int) x, float(x)

Mixed-Mode Expression Different operand types int * float

Overflow/Underflow Too big/small result 9999999999 * 9999999999

Division by zero Illegal math operation 10 / 0


Relational and Boolean Expressions
Programming languages support arithmetic, relational, and Boolean expressions.

1. Relational Expressions

What are Relational Expressions?

• These compare two values using relational operators.

• They return a Boolean result (true or false).

Examples of Relational Operators:

Operator Meaning

== Equal

!= Not equal

< Less than

> Greater than

<= Less than or equal

>= Greater than or 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).

Examples from Different Languages:

• C/C++/Java: != for “not equal”

• Ada: /=

• Lua: ~=
• Fortran: .NE.
• ML/F#: <>

JavaScript & PHP Special Case:

• "7" == 7 → true (because "7" is coerced to a number)

• "7" === 7 → false (because no coercion happens)

Ruby:

• == → checks equality with coercion

• eql? → strict equality without coercion

• === → used only in case statements

Precedence:

• Arithmetic operations happen before relational operations

o Example: a + 1 > 2 * b → arithmetic is evaluated first, then comparison.

2. Boolean Expressions

What are Boolean Expressions?

• Expressions that evaluate to true or false.

• Built using:

o Boolean constants (true, false)

o Boolean variables

o Relational expressions (like x > 5)


o Boolean operators (AND, OR, NOT)
Common Boolean Operators:

Operator Meaning

&& AND

! NOT

xor Exclusive OR (in some languages)

Precedence of Operators (C-style languages):

Precedence Differences:

• In Ada: AND and OR have equal precedence.


• In C-style: AND has higher precedence than OR.

Mixing Expressions:

• You can use:

o Arithmetic in relational (e.g., a + 1 > 5)

o Relational in Boolean (e.g., (a > b) && (b < c))

So, we need different levels of precedence for arithmetic, relational, and Boolean operators.
C/C++ Special Cases:

• C (before C99) had no Boolean type.

o Used integers instead: 0 = false, non-zero = true.


• Example: a > b > c is legal!

o a > b is evaluated first (result is 0 or 1), then compared to c.

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.

Example from Arithmetic:

(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.

Example from Boolean Logic:

(a >= 0) && (b < 10)

• 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.

Why It’s Important (with a Real Code Example):

index = 0;

while ((index < listlen) && (list[index] != key))

index = index + 1;

• If index becomes equal to listlen, then list[index] will crash the program (out-of-range
error).

• But short-circuit saves the day:

o It checks index < listlen first.

o If it’s false, it skips the second part, and avoids the error.

Problem if There’s No Short-Circuit:

• Both sides of the Boolean expression are evaluated always.

• 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).

Problem When There Are Side Effects:

A side effect is when an expression changes a variable (like b++ increases b).

(a > b) || ((b++) / 3)

• If a > b is true, then the second part won’t be evaluated.


• So b++ won’t happen.

• 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

Works with Boolean expressions (like AND, OR)

Does NOT work with Arithmetic expressions (they are always fully evaluated)

Avoids errors Helps prevent things like out-of-range errors

Problem with side


Can skip a variable change unexpectedly
effects

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

• Some languages like Perl allow the target of an assignment to be conditional.

• Example:

3. Compound Assignment Operators

• These are shortcuts like:


• First introduced in ALGOL 68, then used in C, Perl, JavaScript, Python, Ruby, etc.

• You can use them with most binary operators (+, -, *, /, etc.).

4. Unary Assignment Operators


• Operators like ++ (increment) and -- (decrement) are abbreviated assignments.

• Can be prefix (++x) or postfix (x++):

• count++; is the same as count = count + 1;

• When using multiple unary operators:

5. Assignment as an Expression

• In C-like languages, assignment returns a value, so it can be used inside expressions.


Example:

• The parentheses are needed because = has lower precedence than !=.

• if (x = y) ... // mistakenly assigns instead of compares!


• C and C++ allow this mistake.

• Java and C# prevent it by only allowing boolean expressions in if.

6. Multiple Assignments
• Languages like Perl, Ruby, and Lua allow multiple assignments:

• You can swap values like this:

• In Ruby, the same thing is done without parentheses.

7. Assignment in Functional Languages

• In functional languages (like ML, F#), variables don’t change.

• A name like cost is assigned a value once:

• Reassigning cost later makes a new version, the old one is hidden.

• F# uses let instead of val, and let introduces a new scope.

8. Mixed-Mode Assignment

• Happens when variable and value have different types.


• In C, C++, Fortran, Perl, automatic type conversion (coercion) is allowed. Example:
• Ada does not allow this.

• 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;

x = 5.7; // assigning a float (5.7) to an int variable

So here, a float is being assigned to an int → that's a mixed-mode assignment.

The Big Question in Language Design:

Should the programming language allow this?


If yes, should it convert the value (coercion) automatically?

Behavior in Different Languages:

C, C++, Fortran, Perl

• Mixed-mode assignment is allowed.


• They automatically convert (coerce) values to the variable’s type.

Example in C:

float x = 3; // int 3 is converted to float 3.0


int y = 4.8; // float 4.8 is converted to int 4 (decimal is lost)

Flexible, but can lead to unexpected results.

Ada

• Mixed-mode assignment is NOT allowed.

• You must explicitly convert the value.

Example:

x : Integer;
y : Float := 5.5;
x := Integer(y); -- explicit conversion needed

Safer, avoids accidental type issues.

Java and C#

• Allow mixed-mode assignment only when it is safe (called widening conversion).

Widening (safe):

float x = 10; // int to float is OK

Narrowing (unsafe):

int x = 5.7; // ERROR: float to int is not allowed without casting

Improves program reliability and safety.

Functional Languages (like Haskell, Scheme)

• No concept of "assignment" like in imperative languages.

• You just bind names to values, so mixed-mode assignment doesn’t exist.

Summary Table
Mixed-Mode
Language Coercion Allowed? Notes
Assignment?

C/C++/Fortran/Perl Yes Yes (freely) Can lead to silent errors

Ada No No (must cast) Type-safe

Java / C# Partially Allowed Only widening Improves reliability

No (no No variable assignment


Functional Not applicable
assignment) involved

Let me know if you want an example in a specific language or a visual note!

You might also like