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

Programming Language

The document discusses recursive types like lists and trees. It provides examples of lists in various programming languages like Java, Haskell, and Ada. Lists are defined as either empty or consisting of a head element and tail list. Strings are also discussed and can be treated as lists of characters or arrays of characters depending on the language. The document contrasts static and dynamic typing, noting static typing performs type checks at compile-time while dynamic typing does so at run-time. It gives examples of each in Python and Ada. Type completeness is introduced, referring to the operations that can be applied to values of a type.

Uploaded by

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

Programming Language

The document discusses recursive types like lists and trees. It provides examples of lists in various programming languages like Java, Haskell, and Ada. Lists are defined as either empty or consisting of a head element and tail list. Strings are also discussed and can be treated as lists of characters or arrays of characters depending on the language. The document contrasts static and dynamic typing, noting static typing performs type checks at compile-time while dynamic typing does so at run-time. It gives examples of each in Python and Ada. Type completeness is introduced, referring to the operations that can be applied to values of a type.

Uploaded by

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

2

Values and Types


Part 3
▪ Types of values.
▪ Primitive, composite, recursive types.
▪ Type systems: static vs dynamic typing, type completeness.
▪ Expressions.
▪ Implementation notes.
2-1
Recursive types

▪ A recursive type is one defined in terms of itself.


▪ Examples of recursive types:
• lists
• trees

2-2
Lists (1)

▪ A list is a sequence of 0 or more component values.


▪ The length of a list is its number of components. The
empty list has no components.
▪ A non-empty list consists of a head (its first component)
and a tail (all but its first component).
▪ A list is homogeneous if all its components are of the
same type. Otherwise it is heterogeneous.

2-3
Lists (2)

▪ Typical list operations:


• length
• emptiness test
• head selection
• tail selection
• concatenation.

2-4
Lists (3)

▪ For example, an integer-list may be defined recursively to


be either empty or a pair consisting of an integer (its head)
and a further integer-list (its tail):
Integer-List = nil Unit + cons(Integer  Integer-List)
or Integer-List = { nil } { cons(i, l) | i  Integer; l  Integer-List }

where Unit is a type with only one (empty) value.


▪ Solution:
Integer-List = { nil }
{ cons(i, nil) | i  Integer }
{ cons(i, cons(j, nil)) | i, j  Integer }
{ cons(i, cons(j, cons(k, nil))) | i, j, k  Integer }
…

2-5
Example: Java lists (1)

▪ Class declarations for integer-lists:


class IntList {
public int data;
public IntList tail; recursive
public IntList (int d, IntList t) {
data = d; tail = t;
}
}
▪ An integer-list construction:
new IntList(2,
new IntList(3,
new IntList(5,
new IntList(7, null)))));
2-6
Example: Java lists (2)

▪ Class declarations for object-lists:


class List {
public Object data;
public List tail;
public List (Object d, IntList t) {
data = d; tail = t;
}
}

▪ Note that List objects are heterogeneous lists (since


data can refer to an object of any class).
▪ By contrast, IntList objects are homogeneous lists.
2-7
Example: Haskell lists

▪ Type declaration for integer-lists:


data IntList = Nil | Cons Int IntList
recursive
▪ Some IntList constructions:
Nil
Cons 2 (Cons 3 (Cons 5 (Cons 7 Nil)))

▪ Actually, Haskell has built-in list types:


[Int] [String] [[Int]]

▪ Some list constructions:


[] [2,3,5,7] ["cat","dog"] [[1],[2,3]]

2-8
Example: Ada lists

▪ Type declarations for integer-lists:


type IntNode;
type IntList is access IntNode;
type IntNode is record
mutually
data: Integer;
recursive
tail: IntList;
end record;

▪ An IntList construction:
new IntNode'(2,
new IntNode'(3,
new IntNode'(5,
new IntNode'(7, null)))

2-9
Strings

▪ A string is a sequence of 0 or more characters.


▪ Some PLs (ML, Python) treat strings as primitive.
▪ Haskell treats strings as lists of characters. Strings are thus
equipped with general list operations (length, head
selection, tail selection, concatenation, …).
▪ Ada treats strings as arrays of characters. Strings are thus
equipped with general array operations (length, indexing,
slicing, concatenation, …).
▪ Java treats strings as objects, of class String.

2-10
Static vs dynamic typing (1)

▪ Before any operation is performed, its operands must be


type-checked to prevent a type error. E.g.:
• mod operation: check that both operands are integers
• and operation: check that both operands are booleans
• indexing operation: check that the left operand is an array, and that
the right operand is a value of the array’s index type.

2-11
Static vs dynamic typing (2)

▪ In a statically typed PL:


• all variables and expressions have fixed types
(either stated by the programmer or inferred by the compiler)
• all operands are type-checked at compile-time.

▪ Most PLs are statically typed, including Ada, C, C++, Java,


Haskell.

2-12
Static vs dynamic typing (3)

▪ In a dynamically typed PL:


• values have fixed types, but variables and expressions do not
• operands must be type-checked when they are computed at run-
time.

▪ Some PLs and many scripting languages are dynamically


typed, including Smalltalk, Lisp, Prolog, Perl, Python.

2-13
Example: Python dynamic typing (1)

▪ Python function definition: The type of n is unknown.


def even (n): So the “%” (mod) operation
return (n % 2 == 0) must be protected by a run-
time type check.
▪ The types of variables and parameters are not declared, and
cannot be inferred by the Python compiler. So run-time
type checks are needed to detect type errors.

2-14
Example: Python dynamic typing (2)

▪ Python function definition:


def respond (prompt):
# Print prompt and return the user’s response,
# as an integer if possible, otherwise as a string.
try:
response = raw_input(prompt) yields a string
return int(response)
except ValueError: converts the string to an
return response integer, or throws
ValueError if impossible
▪ Application code:
m = respond("Month? ")
if m == "Jan": m = 1
elif m == "Feb": m = 2
2-15
Example: Ada static typing

▪ Ada function definition:


The compiler doesn’t
function is_even (n: Integer) know the value of n.
return Boolean is But, knowing that n’s
begin type is Integer, it infers
return (n mod 2 = 0); that the type of “n mod
end; 2 = 0” will be Boolean.
▪ Call: The compiler doesn’t know the
p: Integer; value of p. But, knowing that p’s
… type is Integer, it infers that the
if is_even(p+1) … type of “p+1” will be Integer.
▪ Even without knowing the values of variables and
parameters, the Ada compiler can guarantee that no type
errors will happen at run-time.
2-16
Static vs dynamic typing (4)

▪ Advantages and disadvantages of static and dynamic typing:


• Static typing is more efficient.
– Dynamic typing requires run-time type checks (which make
the program run slower), and forces all values to be tagged
(to make the type checks possible).
– Static typing requires only compile-time type checks, and
does not force values to be tagged.
• Static typing is more secure: the compiler can guarantee
that the object program contains no type errors. Dynamic
typing provides no such security.
• Dynamic typing is more flexible. This is needed by some
applications where the types of the data are not known in
2-17
advance.
Type completeness (1)

▪ In principle, a value of any type can be:


• assigned
• composed with other values (as components of composite values)
• passed as an argument (to a procedure or function)
• returned as a function result.

▪ But some (mainly older) PLs restrict which of these


operations are applicable to certain types of values.

2-18
Example: type completeness (1)

▪ Ada function and application code:


type Complex is
record x, y: Float; end record;
function sum (c1, c2: Complex)
return Complex is
begin
return (c1.x+c2.x, c1.y+c2.y);
end;
-- Print the complex sum of p, q, and r:
put(sum(sum(p, q), r));

2-19
Example: type completeness (2)

▪ What if Ada function results were restricted to primitive


values?
procedure add (c1, c2: in Complex;
c3: out Complex) is
begin
c3 := (c1.x+c2.x, c1.y+c2.y);
end;
-- Print the complex sum of p, q, and r:
declare
t1, t2: Complex;
begin
add(p, q, t1);
add(t1, r, t2);
put(t2);
end;

2-20

You might also like