Where are variables and methods visible? And when are definitions evaluated?

Declarations and Statements

When you write a Grace module, it normally contains a mixture of declarations and statements.

A declaration introduces a new name. That obviously includes var, def and method declarations. It also includes import declarations, since they introduce a nickname for the imported module object, and dialect declarations, since they introduce a whole bunch of names by logically enclosing the current module with the dialect module.

All of these names are meaningful throughout the whole of the module that you are writing. We say that the scope of each of these names is the whole module. This includes any nested methods or blocks (unless that nested scope re-declares the name as something else).

Order of Initialization

After all of these names have been declared, the code in the module is executed, starting at the top, and proceeding in the order in which the statements and declarations are written. Executing a method declaration does nothing; the method’s name has already been defined, so there is nothing more to be done. Executing a def, however, means work: the expression on the right-hand-side of the def has to be evaluated, and the result bound to the new name. The same is true for a var declaration.

Here is an example:

The names radius, circumference, and circumOfCircleWithRadius are valid throughout the whole module, but before the module is executed, the names radius and circumference are uninitialized. Try moving the print statement to before the def of radius 1 and see what happens. Now move it after the def of radius, but before the def of circumference.

In contrast, the method circumOfCircleWithRadius was defined when it was declared. So, once radius has been initialized to 4, it is possible to evaluate circumOfCircleWithRadius(radius), and bind the result to circumference. It doesn’t matter that the declaration of the method comes after the request.

Summary

  1. All names come into existence together, at the start of a module
  2. The name of a method is bound to its body when the method is declared.
  3. vars and defs are created at the start of the module, but are at first uninitialized.
  4. The code in the module is executed in the order written, top to bottom. This code includes the right-hand-sides of vars and defs, and any statements at the top level. During the excecution process, it’s an error to try to access a variable before it has been initialized.

Consequences

  1. The order in which you write your method declarations doesn’t matter to Grace. Arrange them in a way that makes sense to you as a programmer, e.g., group related methods together.
  2. The order of vars, defs, and top-level method requests, does matter. It is the programmer’s job to make sure that variables are defined before they are used.