Principles of Programming Languages and Systems

by
Peter Fritzson,

PELAB - Programming Environment Laboratory
Dept. of Computer and Information Science,
Linköping University, Sweden

Lecture 2

Attributes, Binding

Binding (p 101)

An unbound symbol n

n
[Graphics:lecture2gr2.gif][Graphics:lecture2gr1.gif]

Bind n to a value

n = 5
[Graphics:lecture2gr2.gif][Graphics:lecture2gr3.gif]

Retrieve the value

n
[Graphics:lecture2gr2.gif][Graphics:lecture2gr4.gif]
Attributes

Make n into a constant

SetAttributes[n, {Constant,Protected}]

Try to change the constant

n = 8
[Graphics:lecture2gr2.gif][Graphics:lecture2gr5.gif]
[Graphics:lecture2gr2.gif][Graphics:lecture2gr6.gif]

The constant is still the same

n
[Graphics:lecture2gr2.gif][Graphics:lecture2gr7.gif]

Retrieve the attributes

Attributes[n]
[Graphics:lecture2gr2.gif][Graphics:lecture2gr8.gif]

Clear the value and the attributes

[Graphics:lecture2gr2.gif][Graphics:lecture2gr9.gif]

Now n has no value, i.e. n is unbound

[Graphics:lecture2gr2.gif][Graphics:lecture2gr10.gif]
[Graphics:lecture2gr2.gif][Graphics:lecture2gr11.gif]

and has no attributes

[Graphics:lecture2gr2.gif][Graphics:lecture2gr12.gif]
[Graphics:lecture2gr2.gif][Graphics:lecture2gr13.gif]
Binding time (p 102, 104)

Static binding

Static binding is done at compile time, before execution.

Dynamic binding

Dynamic binding is done at run time, during execution.
Mathematica has dynamic binding since it is an interpreted language

Symbol table (p 104)

A symbol table for a compiled language maps names to static attributes such as type

For example, as in the example below:

SymbolTable[m, Type] = Integer; 
SymbolTable[x, Type] = Real;

The whole symbol table

[Graphics:lecture2gr2.gif][Graphics:lecture2gr14.gif]
[Graphics:lecture2gr2.gif][Graphics:lecture2gr15.gif]
[Graphics:lecture2gr2.gif][Graphics:lecture2gr16.gif]

Get the type for the variable n

SymbolTable[m, Type]
[Graphics:lecture2gr2.gif][Graphics:lecture2gr17.gif]
Environment (p 105)

The environment in an interpreted language maps names to values and other attributes

Declarations, Blocks, Scope

Blocks (p 106)

begin ... end in Pascal
{ ... } in C
Module[ ... ] in Mathematica

x = 35; (* global x *)

Module[{
x = 999 (* local x *)
},

Print["local x = ", x];
];
[Graphics:lecture2gr2.gif][Graphics:lecture2gr18.gif]

Check the global x again:

[Graphics:lecture2gr2.gif][Graphics:lecture2gr19.gif]
[Graphics:lecture2gr2.gif][Graphics:lecture2gr20.gif]
Lexical scope (p 107-112)

Scope of a declaration
=
region of the the program over which the bindings established by the declaration are maintained

x = 35; (* global x *)

Module[{
y = 999 (* local level 1, y *)
},
Print["level 1 y = ", y];

Module[{
z = 777 (* local level 2, z *)
},
Print["level 2 z = ", z];
Print["global x = ",x];
];

];
[Graphics:lecture2gr2.gif][Graphics:lecture2gr21.gif]
[Graphics:lecture2gr2.gif][Graphics:lecture2gr22.gif]
[Graphics:lecture2gr2.gif][Graphics:lecture2gr23.gif]

Global x is bound to 35, but y and z are unbound at the global level.

[Graphics:lecture2gr2.gif][Graphics:lecture2gr24.gif]
[Graphics:lecture2gr2.gif][Graphics:lecture2gr25.gif]

[Graphics:lecture2gr2.gif][Graphics:lecture2gr26.gif]
[Graphics:lecture2gr2.gif][Graphics:lecture2gr27.gif]

[Graphics:lecture2gr2.gif][Graphics:lecture2gr28.gif]
[Graphics:lecture2gr2.gif][Graphics:lecture2gr29.gif]

Visibility of a declaration (p 112)
=
visibility includes only those regions where the bindings of a declaration apply

(However, scope may include scope holes (as in Ada))

Visibility by selection (p 112)
e.g.:
example.field
makes field accessible

Nested Lexical scope (p 112)

Inner declarations take precedence

x = 35; (* global x *)

Module[{
x = 999 (* local level 1, x *)
},
Print["level 1 x = ", x];

Module[{
x = 777 (* local level 2, x *)
},
Print["level 2 x = ", x];
];

];
[Graphics:lecture2gr2.gif][Graphics:lecture2gr30.gif]
[Graphics:lecture2gr2.gif][Graphics:lecture2gr31.gif]

Lexical scope and dynamic scope

Lexical scope (p 116)

Variables are interpreted according to the reading of the program;

Types can be static

Used by modern languages

x = 35; (* global x *)

p[] := Module[{
},
Print[x];
];

q[] := Module[{
x = 2
},
p[];
];

x = 1;
q[];
[Graphics:lecture2gr2.gif][Graphics:lecture2gr32.gif]
Dynamic scope (p 116)

Variables are interpreted according to dynamic call chain of functions;

Types cannot in general be static

Used by older languages

Consider the call chain: main > call of q > call of p
Block[] is the Mathematica construct for dynamically scoped blocks.

x = 35; (* global x *)

p[] := Block[{
},
Print[x];
];

q[] := Block[{
x = 2
},
p[];
];

x = 1;
q[];
[Graphics:lecture2gr2.gif][Graphics:lecture2gr33.gif]

Expression evaluation (p 138)

Expressions

Always return a value

Pure expressions produce no side effects

z = 66; 
x = (y = z)
[Graphics:lecture2gr2.gif][Graphics:lecture2gr34.gif]

Lisp, Mathematica, C are expression languages: everything can return a value

Statements

Return no value

Produce side effects

z = 66; 

z
[Graphics:lecture2gr2.gif][Graphics:lecture2gr35.gif]
Evaluation order

Applicative (strict) evaluation
=
always evaluate arguments before invoking the operation

(3 + 4)*(5 - 6)
[Graphics:lecture2gr2.gif][Graphics:lecture2gr36.gif]

Hold[(3 + 4)*(5 - 6)]//FullForm
[Graphics:lecture2gr2.gif][Graphics:lecture2gr37.gif]

Evaluate arguments to the Times operator before calling Times:

[Graphics:lecture2gr2.gif][Graphics:lecture2gr38.gif]
[Graphics:lecture2gr2.gif][Graphics:lecture2gr39.gif]
Short-circuit boolean operators (p 142)

[Graphics:lecture2gr2.gif][Graphics:lecture2gr40.gif]

False && Print["foo"];

And[True, Print["foo"]]
[Graphics:lecture2gr2.gif][Graphics:lecture2gr41.gif]
Evaluation order and side effects (p 141)

f[] := Module[{},
x = x+1;
Return[x]
];

p[a_,b_] := Module[{},
Return[b+a]
];

x = 1;
Print[p[f[],x]]
[Graphics:lecture2gr2.gif][Graphics:lecture2gr42.gif]

Left to right evaluation order gives 4. Right to left order would give 3.

Delayed evaluation (normal order evaluation) (p 144)

[Graphics:lecture2gr2.gif][Graphics:lecture2gr43.gif]

Both sq and sq2 uses normal-order evaluation.

[Graphics:lecture2gr2.gif][Graphics:lecture2gr44.gif]
[Graphics:lecture2gr2.gif][Graphics:lecture2gr45.gif]

[Graphics:lecture2gr2.gif][Graphics:lecture2gr46.gif]
[Graphics:lecture2gr2.gif][Graphics:lecture2gr47.gif]

Data types (p 154)

Definition 1. (p156)
A data type is a set of values
Definition 2.
A data type is a set of values,
together with a set of operations on those values having certain properties
Overloading of operations

g[x_Integer,y_Integer] := Plus[x,y];

g[x_Real,y_Real] := Plus[1000.,x,y];

g[x_List,y_List] := Union[x,y];

Invoking the integer version

g[3,5]
[Graphics:lecture2gr2.gif][Graphics:lecture2gr48.gif]

Calling the real version

g[3.,5.]
[Graphics:lecture2gr2.gif][Graphics:lecture2gr49.gif]

A version with mixed integer and real arguments is not defined. g is not called. The call remains unevaluated.

[Graphics:lecture2gr2.gif][Graphics:lecture2gr50.gif]
[Graphics:lecture2gr2.gif][Graphics:lecture2gr51.gif]

Calling the set union version

[Graphics:lecture2gr2.gif][Graphics:lecture2gr52.gif]
[Graphics:lecture2gr2.gif][Graphics:lecture2gr53.gif]

Defining a mixed integer/real version

g2[x:(_Real | _Integer), y_Real] := Plus[500.,x,y];

g2[3, 55.]
[Graphics:lecture2gr2.gif][Graphics:lecture2gr54.gif]

g2[3., 55.]
[Graphics:lecture2gr2.gif][Graphics:lecture2gr55.gif]