next up previous contents
Next: Independent Scopes Up: Procedures Previous: Commenting a Procedure: description

   
Scoping Rules

The scope of a name (variable names, data structure names, procedure names) is the part of the program within which the name can be used. Darwin employs dynamic scoping, that is, Darwin does not require that you declare variables before you use them.3.1 Thus,

> x := 5:
> x := x * 99:
> y := z:
are perfectly digestible by the Darwin system. This section explores the scoping rules employed by Darwin for variables, structures and routines. Instead of a formal description of the scoping rules Darwin uses, we use a series of examples which covers all cases one would normally encounter when writing programs.

So far all of the names we have defined have been global meaning their scope is the entire Darwin environment. There are situations when we do not necessarily want some variables to be visible to the entire world. The temporary variables created by procedures are a common example of this; the variables have no meaning outside of the scope of the procedure and should therefore only be accessible from inside that routine. We term such variables local variables. Observe the role of total in the example below.

> new_SetAverage := proc( s : set(real) )
>   local total;
>   description 'This procedure takes a set of real values as an 
>                argument and calculates the average value in the set';
>   total := 0:
>   for i from 1 to length(s) do
>     total := total + s[i];
>   od;
>   print('The average is ', total/length(s));
> end:
Since variable total is used as a ``scratch'' variable during the computation of the average, no other procedure would require use of it. Therefore, it is advisable to make it local to the routine. To do this, we declare total to be of type local and now it is visible only within the body of procedure NewSetAverage. This explicit declaration is optional in Darwin. If you compare procedure NewSetAverage with the previous versions of SetAverage, you will see that we dynamically defined total. What does Darwin do when it encounters a name that has not yet been declared? This is an easy question with a complicated answer. The dogma we suggest you adhere to goes something like as follows:
the best way to learn the Darwin scoping rules is through experimentation; the best way to avoid learning the Darwin scooping rules is through always declaring your local variables.

When you begin to write large programs, subtle scoping problems may arise. These can be particularly difficult to pinpoint and remove. The explicit declaration of a local variable helps to document your code and provides some help for Darwin in determining the intent of your program.

We can use the built-in assigned function to test the scope of a variable. The function
assigned(t : name)
takes a parameter t of type name and returns true if t is currently being used as a name in this scope. Otherwise, it returns false.

> assigned(total);                # check to see if total is a variable
>                                 #    from outside of the procedure
> SetAverage({5, 10, 15});        # call the procedure
> assigned(total);                # check to see if total is a
>                                 #    variable now from outside the
>                                 #    proc

Any local declarations must appear directly after the procedure declaration. They may follow or precede global declarations (see §[*] below) but must precede any option commands (§[*]) or the description command (§[*]). If there is more than one local variable, they must be separated by commas.

> example := proc( )
>   local x, y, z;
>   global a, b, c;
>   option polymorphic;
>   description 'A description of the procedure';

> end:



 
next up previous contents
Next: Independent Scopes Up: Procedures Previous: Commenting a Procedure: description
Gaston Gonnet
1998-09-15