Principles of Programming Languages and Systems

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


Bind n to a value

n = 5

Retrieve the value


Make n into a constant

SetAttributes[n, {Constant,Protected}]

Try to change the constant

n = 8

The constant is still the same


Retrieve the attributes


Clear the value and the attributes


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


and has no attributes

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


Get the type for the variable n

SymbolTable[m, Type]
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 *)

x = 999 (* local x *)

Print["local x = ", x];

Check the global x again:

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 *)

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

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


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




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)
makes field accessible

Nested Lexical scope (p 112)

Inner declarations take precedence

x = 35; (* global x *)

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

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


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[{

q[] := Module[{
x = 2

x = 1;
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[{

q[] := Block[{
x = 2

x = 1;

Expression evaluation (p 138)


Always return a value

Pure expressions produce no side effects

z = 66; 
x = (y = z)

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


Return no value

Produce side effects

z = 66; 

Evaluation order

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

(3 + 4)*(5 - 6)

Hold[(3 + 4)*(5 - 6)]//FullForm

Evaluate arguments to the Times operator before calling Times:

Short-circuit boolean operators (p 142)


False && Print["foo"];

And[True, Print["foo"]]
Evaluation order and side effects (p 141)

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

p[a_,b_] := Module[{},

x = 1;

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

Delayed evaluation (normal order evaluation) (p 144)


Both sq and sq2 uses normal-order evaluation.



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


Calling the real version


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


Calling the set union version


Defining a mixed integer/real version

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

g2[3, 55.]

g2[3., 55.]