PLP: Lecture 20
Orthogonality
Features can be used in any combination.
Example:
Algol-orthogonality was major design goal. Expression oriented; no separate notion of statements
begin
a := if b < c then d else e; // rhs is expression
a := begin f(b); g(c) end; // value of rhs is g(c), rhs is a statement though
g(d); // return value of g(d) thrown away
2 + 3; // value of code block
end
Even the entire above block is an expression, and its return value is 5.
In Java, b < c ? d : e
is equivalent- returns a value.
C takes an intermediate approach.
- distinguishes between statements and expressions
- one class of expression is expression statement, which computes the value of expression and throws it away.
- assignments can appear in expressions
- in any context that expects a
boolean
, C accepts anything that can be coerced into anint
Other features
- Combinational assignment operators such as
+=
and*=
- Multiway assignment such as
a,b,c := d,e,f
. Allows functions to return multiple values
Initialization
Specifying initial value of a variable in its declaration. Initial value of statically allocated variables can be set by compiler.
Orthogonality requires a way to initialize composite types. Only saves time for statically allocated variables. Other initialization is done at runtime.
Definite Assignment
Require that a value be “definitely assigned” to a variable before the variable is used in any expression. Every possible control path to an expression must assign a value to every variable in the expression. This is the case in Java and C# for all but local variables in a subroutine.
Dynamic checks can fail as semantic errors at runtime. Expose some subtle bugs that could exist with compiler supplying default values. Happens in C++.
Ordering within expressions
(a + b) * (c + d)
? Most languages do not specify order, allowing compiler to choose. Java and C# require left-to-right.
Mathematical Identities
- commutativity is assumed to be safe
- associativity (known to be dangerous)
(a + b) = c
works ifa=maxint
andb=minint
andc < 0
a + (b + c)
does not
- inviolability of parantheses (language RESPEKS parantheses)
Short circuit evaluation
a(x) && b(y)
- can evaluate left to right, and stop ifa(x)
if falsea(x) || b(y)
- no point in evaluatingb(y)
ifa(x)
is true- this is often more efficient
- Changes semantics, e.g.,
if (z != null && z.w > 0)
… - If subexpressions have side effects, short circuits may not be desireable. Ada does both!
Sequence points
C, C++ define “sequence points” that constrain order of evaluation. Between SPs, order is unconstrained. There are few SPs, which can lead to unpleasant surprises. For e.g.,
- At the end of a full expression, terminated usually by ;
- after eval of all fn args in a fn call and before execution of any exprs in the fn body
- after cpying of a rtrnd value and before execution of any exprs outside the fn
- after evaluation of the first exprsn in
a&&b
,a||b
,a?b:c
, ora,b
- after the init of each base and member in the constructor init list
Example:
Assume i has value 1 before the expression
x[i] = i++ + 1
Don’t know if we are storing at x[1] or x[2]!
Example:
Assume i==1, j==2
f(i++, j++, i+j)
In C, don’t know what gets passed to f in the 3rd parameter. No sequence points constrain the order of evaluation of these args