Variables may or may not be initialised at declaration. For example:
var
name : String
n : Integer := 42
cnt : Integer := getNumElems (1, true)
Variables are a combination of type, state and value. If a variable is not initialised, its state is undefined. An attempt to use an undefined variable is noticed at runtime and results in a runtime error. The use of a variable is its appearance on the right hand side of an assignment or in an actual parameter list. Routine results are checked at the time of return from the routine.
This catches a common error made by beginning students. Checking for uninitialised variables is a case where Blue, by concentrating on a teaching situation, can provide better support for students than other systems. Undertaking the checks costs in both time and space. In a language intended for commercial production, efficiency would take precedence over error checking, and those checks would not be justifiable. (In fact, the only other language known to us which defines such checking is CLU, but this part of the language definition was never implemented in the compiler [Liskov 1992]. Java defines related, but slightly different semantics: access to variables which
may be uninitialised is considered an error. The checking is done by using compile
time flow analysis, and cases that cannot be decided at compile time are simply disallowed.)
Alternatives to this mechanism would have been to force initialisation at point of declaration, or to automatically initialise all variables to some default value. Both schemes have drawbacks.
Forced initialisation
Forcing initialisation effectively means that declarations should be allowed anywhere in the code. At the point of Blue declarations (before the start of a routine) sensible initial values are often not known, thus making forced initialisations meaningless (because they would only force the programmer to initialise variables to some meaningless value). Meaningful initialisation values are often only known halfway through a routineÕs body. To achieve meaningful variable initialisation at declaration point, the declaration must be allowed at the point at which the variable is first used. C++, for instance, follows this approach.
We have already argued that variable declarations scattered through the code are detrimental to readability. (This is magnified in languages with nested blocks that
CHAPTER 6: THE BLUE LANGUAGE
allow multiple nested declarations of the same variable name.) C++, by allowing scattered declarations and not demanding variables to be initialised (together with the inability to check for the use of uninitialised variables) provides the worst of all worlds.
Automatic initialisation
The other alternative, automatic initialisation, also is not appropriate for a teaching language. There are three possible scenarios, all of which are negative:
1 The user forgets to initialise the variable; the variable is automatically initialised to a value that is semantically illegal in the context (e.g. nil for a variable that is expected to refer to an object). In this situation, the initialisation is no better than no initialisation at all. The program will fail, as it would have without any initialisation.
2 The user forgets to initialise the variable; the variable is automatically initialised to a value that is semantically legal in the context (e.g. 0 for an integer variable). In this case, the user will be ÒprotectedÓ from detecting a program error. Because the value is legal, it will not result in an (immediate) error, but it may nonetheless be wrong and cause wrong results. It is only detected later. This is the worst case for a teaching language, because programming errors may go unnoticed altogether.
3 The user intentionally omits the initialisation of the variable because the default value is the intended initial value (i.e. the user exploits the automatic initialisation). The only real effect of this case is to save typing of a few characters (the explicit initialisation), thereby reducing readability (since the reader must know the default value for each particular type of variable). It is also not clear whether the initialisation was consciously or unconsciously omitted. It seems worth the effort on the writers part of including the initialisation explicitly in these cases to clarify the semantics to the reader.
The Blue mechanism combines the best features of all schemes: all declarations are placed in a well-defined location, variables may be initialised if a sensible initial value is known (with the initial value clearly readable in the source text) and the use of uninitialised variables is always detected.
6.8.2 Nil
A variable of any type may hold the special value nil. Since all variables hold references to objects, all variables, including simple types such as Integer or Boolean, can hold the nil value. Nil indicates that the variable currently does not hold any
CHAPTER 6: THE BLUE LANGUAGE
reference.7 Nil differs from all other legal values of the type (i.e it is not, for instance, 0 for integer variables).
Nil therefore is special, since it does not seem to conform to the strongly typed system that Blue otherwise enforces. Consider:
var a : Integer b : MyClass ... a := nil b := nil
The type of nil cannot be determined - it is assignment compatible with all types. Most other languages face the same issue, and there are different technical tricks to provide an answer to this problem. (Note that this only poses a problem for the theoretical foundation, the type system. It is not normally a problem in practical application.)
Blue, like Pascal, uses an overloaded nil value. Nil is considered to represent a value of every type (therefore a potentially unlimited number of nil values exist) and the overloaded assignment automatically assigns the nil value of the right type to the variable.
Beta, on the other hand, defines a class named ÒNoClassÓ, which implicitly inherits from all existing classes. Nil is of this class and therefore, by subtyping rules, assignment compatible to all types. Eiffel uses the same construct with a class named "None".
An early development version of Blue answered this question by using the state and
value distinction. A variable has a state in addition to its value. We have already
discussed the undefined state. A variable has the state valid if it has been assigned a value. (Once a variable leaves the undefined state, it can never return to that state. No test for undefined exists. A programmer in a well written program always knows when a variable is undefined.)
The earlier version considered nil to be a state rather than a value. This subtle distinction avoids the type problem. To meet the requirement of consistent syntax (Òsame syntax for same semantics, different syntax for different semanticsÓ), however, the change to the nil state should not be written as an assignment (since it is a semantically different operation). We therefore defined built-in commands to set and test for nil:
7
Note that this does not mean that simple types must be implemented as a reference type. In fact, in the current Blue system they are not. However this is an implementation optimisation and does not affect the conceptual model.
CHAPTER 6: THE BLUE LANGUAGE
set_nil (a)
if is_nil (a) then ...
end if
A side effect of this definition was that nil could not be easily passed as a parameter. This problem prompted us to view nil as a value rather than a state, and to accept the overloading of its type.
6.9 Statements
The statements in Blue are · assignment
· assignment attempt · procedure call · return
· assertion
and control structures (which are discussed later).