module 2 Flashcards
data type
defines a collection of data objects and a set of predefined
operations on those objects
descriptor
collection of the attributes of a variable
object
an instance of a user-defined (abstract data) type
One design issue for all data types
What operations are defined and how are
they specified?
primitive data types
- Almost all programming languages provide a set of primitive data types
- not defined in terms of other data types
- Some primitive data types are merely reflections of the hardware
- Others require only a little non-hardware support for their implementation
primitive data type examples
Integer
Floating Point
Complex
Decimal
Boolean
Character
Value
sequences of characters
design issues of character strings
Is it a primitive type or just a special kind of array?
Should the length of strings be static or dynamic?
typical string operations
§Assignment and copying
§Comparison (=, >, etc.)
§Catenation
§Substring reference
§Pattern matching
ordinal type
one in which the range of possible values can be easily
associated with the set of positive integers
examples of ordinal types in java
§integer
§char
§boolean
Enumeration Types
All possible values, which are named constants, are provided in the definition
design issues of enumeration
§Is an enumeration constant allowed to appear in more than one type definition, and if
so, how is the type of an occurrence of that constant checked?
§Are enumeration values coerced to integer?
§Any other type coerced to an enumeration type?
array design issues
- What types are legal for subscripts?
- Are subscripting expressions in element references range checked?
- When are subscript ranges bound?
- When does allocation take place?
- Are ragged or rectangular multidimensional arrays allowed, or both?
- What is the maximum number of subscripts?
- Can array objects be initialized?
- Are any kind of slices supported?
4 categories of arrays
- Static: subscript ranges are statically bound and storage allocation is static
(before run-time):
§Advantage: efficiency (no dynamic allocation) - Fixed stack-dynamic: subscript ranges are statically bound, but the allocation is
done at declaration time:
§Advantage: space efficiency - Fixed heap-dynamic: similar to fixed stack-dynamic: storage binding is dynamic
but fixed after allocation (i.e., binding is done when requested and storage is
allocated from heap, not stack) - Heap-dynamic: binding of subscript ranges and storage allocation is dynamic
and can change any number of times:
§Advantage: flexibility (arrays can grow or shrink during program execution)
rectangular array
multi-dimensioned array in which all of the rows have
the same number of elements and all columns have the same number of
elements
F# and C# support rectangular arrays and jagged arrays
jagged matrix
has rows with varying number of elements:
§Possible when multi-dimensioned arrays actually appear as arrays of arrays
C, C++, and Java support jagged arrays
slice
some substructure of an array; nothing more than a referencing
mechanism
Slices are only useful in languages that have array operations
Access function
maps subscript expressions to an address in the array
for single-dimensioned arrays:
address(list[k]) =
address (list[lower_bound]) + ((k-lower_bound) * element_size)
record
a possibly heterogeneous aggregate of data elements in which the
individual elements are identified by names
design issues for records
§What is the syntactic form of references to the field?
§Are elliptical references allowed
tuple
data type that is similar to a record, except that the elements are not
named
Used in Python, ML, and F# to allow functions to return multiple values
Python:
§Closely related to its lists, but immutable
Lists
in Lisp and Scheme are delimited by parentheses and use no commas
union
a type whose variables are allowed to store different type values at
different times during execution
design issue for unions
Should type checking be required?
Discriminated vs. Free Unions
free union: C and C++ provide union constructs in which there is no language support for
type checking
discriminated: each union include a type indicator called a
discriminant (Supported by ML, Haskell, and F#)
pointer type variable
a range of values that consists of memory addresses
and a special value
* Provide the power of indirect addressing
* Provide a way to manage dynamic memory
* A pointer can be used to access a location in the area where storage is
dynamically created (usually called a heap)
Design Issues of Pointers
- What are the scope of and lifetime of a pointer variable?
- What is the lifetime of a heap-dynamic variable?
- Are pointers restricted as to the type of value to which they can point?
- Are pointers used for dynamic storage management, indirect addressing, or
both? - Should the language support pointer types, reference types, or both?
Problems with Pointers
- Dangling pointers (dangerous):
§A pointer points to a heap-dynamic variable that has been deallocated - Lost heap-dynamic variable:
§An allocated heap-dynamic variable that is no longer accessible to the user program
(often called garbage):
o Pointer p1 is set to point to a newly created heap-dynamic variable
o Pointer p1 is later set to point to another newly created heap-dynamic variable
o The process of losing heap-dynamic variables is called memory leakage
Reference Types
used
primarily for formal parameters:
§Advantages of both pass-by-reference and pass-by-value
- Java extends C++’s reference variables and allows them to replace pointers
entirely:
§References are references to objects, rather than being addresses - C# includes both the references of Java and the pointers of C++
Type checking
the activity of ensuring that the operands of an operator are of
compatible types
compatible type
one that is either legal for the operator, or is allowed under
language rules to be implicitly converted, by compiler-generated code, to a legal
type: this automatic conversion is called a coercion
Type error
the application of an operator to an operand of an inappropriate type
If all type bindings are static…
nearly all type checking can be static
If type bindings are dynamic…
type checking must be dynamic
what makes a programming language strongly typed?
type errors are always detected
Advantage of strong typing
allows the detection of the misuses of variables that
result in type errors
examples of strong typing
- Language examples:
§C and C++ are not: parameter type checking can be avoided; unions are not type
checked
§Java and C# are, almost: because of explicit type casting
§ML and F# are - Coercion rules strongly affect strong typing: they can weaken it considerably
(C++ versus ML and F#) - Although Java has just half the assignment coercions of C++, its strong typing is
still far less effective than that of Ada
Name type equivalence
means the two variables have equivalent types if they
are in either the same declaration or in declarations that use the same type
name
Easy to implement but highly restrictive:
§Subranges of integer types are not equivalent with integer types
§Formal parameters must be the same type as their corresponding actual parameters
Structure Type Equivalence
means that two variables have equivalent types if
their types have identical structures
More flexible, but harder to implement
what are the problems with structured type equivalence?
Consider the problem of two structured types:
§Are two record types equivalent if they are structurally the same but use different
field names?
§Are two array types equivalent if they are the same except that the subscripts are
different?
e.g., [1..10] and [0..9]
§Are two enumeration types equivalent if their components are spelled differently?
§With structural type equivalence, you cannot differentiate between types of the same
structure:e.g., different units of speed, both float
expressions
the fundamental means of specifying computations in a
programming language
To understand expression evaluation, need to be familiar with the orders of
operator and operand evaluation
dominant role of assignment statements
Essence of imperative languages
one of the motivations for the development of the first
programming languages
Arithmetic evaluation
Arithmetic expressions
consist of operators, operands, parentheses, and function calls
In most languages, binary operators are
infix, except in Scheme and LISP, in which
they are prefix; Perl also has some prefix binary operators
Most unary operators are
prefix, but the ++ and –- operators in C-based languages
can be either prefix or postfix
Typical precedence levels (operators)
§parentheses
§unary operators
§** (if the language supports it)
§*, /
§+, -
Operator Precedence Rules
define the order in
which “adjacent” operators of different precedence levels are evaluated in expressions
Operator Associativity Rule
define the order in
which adjacent operators with the same precedence level are evaluated
Typical associativity rules:
Left to right, except **, which is right to left
Sometimes unary operators associate right to left (e.g., in FORTRAN)
Precedence and associativity rules can be overriden with
parentheses
Operand evaluation order
§Variables: fetch the value from memory
§Constants: sometimes a fetch from memory; sometimes the constant is in the machine language instruction
§Parenthesized expressions: evaluate all operands and operators first
§The most interesting case is when an operand is a function call
Two possible solutions to the problem of functional side effects
§Write the language definition to disallow functional side effects:
o No two-way parameters in functions
o No non-local references in functions
o Advantage: it works!
o Disadvantage: inflexibility of one-way parameters and lack of non-local references
§Write the language definition to demand that operand evaluation order be fixed:
o Disadvantage: limits some compiler optimizations
o Java requires that operands appear to be evaluated in left-to-right order
referential transparency
if any two expressions in
the program that have the same value can be substituted for one another anywhere in the program, without affecting the action of the program
Advantage of referential transparency
Semantics of a program is much easier to understand if it has referential
transparency
operator overloading
Use of an operator for more than one purpose
Some are common (e.g., + for int and float)
Some are potential trouble (e.g., * in C and C++):
§Loss of compiler error detection (omission of an operand should be a detectable
error)
§Some loss of readability
narrowing conversion
converts an object to a type that cannot
include all of the values of the original type e.g., float to int
widening conversion
an object is converted to a type that can
include at least approximations to all of the values of the original type, e.g., int
to float
Relational Expressions
- Use relational operators and operands of various types
- Evaluate to some Boolean representation
- Operator symbols used vary somewhat among languages (!=, /=, ~=, .NE.,
<>, #)
Boolean Expressions
Operands are Boolean and the result is Boolean
Short Circuit Evaluation
An expression in which the result is determined without evaluating all of the operands and/or operators
Example: (13 * a) * (b / 13 – 1)
§If a is zero, there is no need to evaluate (b /13 - 1)
types of assignments
- Functional language: expressions are the building blocks:
§If computation is expression evaluation that depends only on the referencing
environment for that evaluation
§Expressions in a purely functional language are referentially transparent: value
depends only on the referencing environment - Imperative language: computation usually ordered series of changes to the
values of variables in memory:
§Assignments provide the principal means for these changes