CSE130 LECTURE NOTES

April 29, 2002
 
 

ADMINISTRATION

We handed back the first assignment last Friday.  To check your score, see www.gradesource.com
 
 

(DIS)ADVANTAGES OF DYNAMIC SCOPING

Definition: Dynamic scoping is the policy that an applied appearance (i.e. a use) of an identifier (i.e. a name) refers back to the declaration of this identifier in the most recently entered scope that does have a declaration for this identifier.

Under static scoping, if all function values are created at compile-time, then identifiers can be discarded at run-time, because each use of an identifier can be compiled into a stack offset.

Dynamic scoping requires keeping knowledge of names at runtime. Names refer to values in the most recently entered scope, which can only be known at runtime.

Sometimes dynamic scoping is convenient.  The behavior of a function can be changed without recompiling, just by calling it from inside an environment where global identifiers have different bindings.

However the same behavior can be obtained with static scoping and assignment:

var s = 10.0;
function scale (x: real): real;
begin
    return x*s;
end;

procedure update (v: vector);
begin
    var l: integer := length(v);
    s := norm(v);
    for j := 1 to l do scale(v[i])
end;

Dynamic scoping makes programs harder to understand.  The example above shows that assignment commands also make programs harder to understand.

Dynamic scoping violates alpha-conversion: if the name s in the update procedure body was changed to t, under dynamic scoping a different effect is obtained.

The fundamental advantage of functional programming languages is that they are easier to understand, because they do not have the complexity of assignment commands.

If a program is easier to understand, it is also easier for a compiler to optimize.

 

LIFETIMES

Variables have scopes, and they also have lifetimes. The two concepts are distinct: Every variable starts existing at a certain time, then stops existing at some time later.  The general rule for determining a variable's lifetime is that it is the timespan of execution of the block in which the variable is declared.

For example the lifetime of s above is the execution of the whole program, while the local variable l has many lifetimes. Each lifetime of l is one execution of the body of update.  Conceptually, update has new local variables at each call, which just happen to have the same name as previously existing variables.

Note that the executions of blocks are always strictly nested. They can't overlap, so the lifetimes of variables declared in blocks also cannot overlap.

If memory for a variable is allocated and deallocated explicitly by the programmer, then lifetimes can overlap.  For example:

malloc(x);
malloc(y);
free(x);
free(y);
This example shows that heap-based variables are harder to understand (because they have more freedom) than variables declared in the regular way.  regular variables are called stack variables because memory management for them can be done in a very simple way, with push and pop operations on a stack.
 
 

PERSISTENT VARIABLES

Definition: A persistent variable is one that keeps its value after program execution, and that has an initial value before program execution.

The most common persistent variables are files.  Pascal programs typically use what is called a persistent variable: the file named input.

Most languages have implementation-dependent restrictions on persistent variables. For example in Pascal a persistent variable must be of the type file of X   for some component type X.

These limitations were to take account of implementation constraints, but they are excessive. For example Pascal has no random-access files.
 
 

OWN VARIABLES

A variable that keeps its value across different calls to a procedure (or function), but can only be updated inside the procedure, is global in lifetime, but local in scope.

A variable with this behaviour is called a static variable in C, or called an own variable in Algol 60.

One important use for such a variable is to keep track of the seed used by a pseudo-random number generator:

function prng (): int;
    static var seed : int = initialval;
begin
    seed := update(seed);
    return transform(seed);
end;
Here, we do not want the variable seed to have a new lifetime each time prng is called, but we do want this variable to be visible only inside prng.
 
 



Copyright (c) by Charles Elkan, 2002.