Roles of Variables Home Page

An Introduction to the Roles of Variables

Jorma Sajaniemi

In programming, variables are not used in a random or ad-hoc way but there are several standard use patterns that occur over and over again. For example, consider the following Pascal program:

program doubles; var data, count, value: integer; begin repeat write('Enter count: '); readln(data) until data > 0; count := data; while count > 0 do begin write('Enter value: '); readln(value); writeln('Two times ', value, ' is ', 2*value); count := count - 1 end end.

In this program, there are three variables: data , count , and value . In the first loop, a user is requested to enter the number of values to be later processed in the second loop. This number is requested repeatedly until the user gives a positive value. The variable data is used to store the latest input read, and there is no possibility for the program to guess what values the user will enter.

The variable value is used similarly in the second loop: it stores the latest input, and there is no known relation between its successive values.

The variable count , however, behaves very differently. Once it has been initialized its future values will be known exactly: it will step downwards one by one until it reaches its limiting value, i.e. zero.

In the following the variables data and value are said to have the role most-recent holder (as they store the latest value in some value succession - user input in this case), and the variable count is said to be a stepper. These roles occur in programs again and again. In fact, only ten roles are needed to cover 99 % of all variables in novice-level programs.

Roles are not a special property of procedural programming but they apply to other programming paradigms, also. For example, consider the following Java class:

public class Dog { String name; int age; public Dog (String n) { name = n; age = 0; } public void birthday () { age++; } }

Objects of this class have two attributes: name and age . The value of the attribute name does not change after initialization; it is a fixed value. The attribute age behaves similarly to the variable count in the Pascal program: it steps through a known sequence (1, 2, 3, ... in this case) and its role is stepper.

In order to see that the attribute age is increased repeatedly, we must assume that the method birthday is called repeatedly. This can be verified only by looking at other classes: do they call the method at all, and if so, does it happen several times. In object-oriented programming control flow is harder to reveal than in procedural programming; consequently, roles of attributes may be harder to find out than roles of variables in procedural programming. This does not, however, mean that roles would be less important in object-oriented programming. On the contrary, explicit role information in the form of comments written by the author of a program may help in program comprehension, e.g., in maintenance tasks; knowing that a variable is, say, a stepper and not a fixed value, indicates the succession of values it may obtain and makes program understanding easier.

In procedural programming roles apply to variables and parameters. In object-oriented programming roles apply also to attributes and objects that encapsulate a single conceptual attribute, e.g., String in Java. In functional programming there are no variables. However, function parameters as well as return values of recursive functions have role-like behavior. For example, consider the following ML function:

fun max(a, nil) = a | max(a, (h::t)) = if h>a then max(h,t) else max(a,t)

h

a

Thus roles apply to procedural, object-oriented, and functional programming but the set of entities that have roles is different in different paradigms. In the following, the term "variable" is used for brevity to cover all the different cases in different programming paradigms.

The Role Concept

The role of a variable characterizes the dynamic nature of the variable, e.g., a stepper goes through a succession of values that is usually known in advance as soon as the succession starts. A role is not supposed to be a unique task in some specific program (e.g., the stepper that controls the number of values processed in the previous program) but a more general concept characterizing many variables in various programs.

The role of a variable can be defined to be the dynamic character of a variable embodied by the succession of values the variable obtains, and how the new values assigned to the variable relate to other variables. In particular, the role concept does not concern the way a variable is used in the program. For example, a stepper is a stepper whether it is used to reference elements in an array, or perhaps in producing diagnostic output for debugging purposes. Thus, a role does not consider the way a variable is used but looks at the succession of values it will encounter and how this depends on other variables.

For example, the role most-wanted holder is attached to variables that store the best value encountered so far in going through a succession of values as opposed to most-recent holders that store every value in a succession. Consider the following program:

program largest; var data, largest: integer; begin largest := 0; repeat write('Enter a positive number, end with 0: '); readln(data); if data > largest then largest := data until data = 0; writeln('The larges number was ', largest) end.

data

largest

data

largest

Eleven roles that cover practically all variables in novice-level programs in object-oriented, procedural and functional programming are the following (green for all variables, blue for data structure use):

Role (v. 2.0) Example Informal definition Fixed value maxStringLength A data item that does not get a new proper value after its initialization Stepper count A data item stepping through a systematic, predictable succession of values Most-recent holder inputData A data item holding the latest value encountered in going through a succession of unpredictable values, or simply the latest value obtained as input Most-wanted holder maximum A data item holding the best or otherwise most appropriate value encountered so far Gatherer sum A data item accumulating the effect of individual values Follower prev A data item that gets its new value always from the old value of some other data item One-way flag errorsOccurred A two-valued data item that cannot get its initial value once the value has been changed Temporary temp A data item holding some value for a very short time only Organizer sortArray A data structure storing elements that can be rearranged Container processQueue A data structure storing elements that can be added and removed Walker currNode A data item traversing in a data structure

The above definition of the roles are informal but sufficient for student use. More detailed definitions can be found here.

Role Changes

The role of a variable may change during its lifetime. For example, consider a slight modification of the program at the beginning of this page:

program doubles; var count, value: integer; begin repeat write('Enter count: '); readln(count) until count > 0; while count > 0 do begin write('Enter value: '); readln(value); writeln('Two times ', value, ' is ', 2*value); count := count - 1 end end.

Now the variable count is a most-recent holder in the first loop and a stepper in the second loop. Usually such role changes occur between main parts of a program.

Role changes are of two basic types. In a proper role change the final value of the variable in the first role is used as the initial value for the next role. For example, the role change in the previous program is a proper one. In a sporadic role change the variable is re-initialized with a totally new value at the beginning of the new role phase. A sporadic role change means sometimes bad usage of variables with the intention to "save" memory.

Special Cases

In the case of simple variables (integers, reals etc.) each variable has a single role at a time. Pointers are treated just like other variables; in particular, the role of a pointer describes how the pointer behaves and not how the pointed variable behaves. Dynamic variables can in principle be treated similarly to static variables.

An array is considered to have a single role, determined by the roles of its elements, e.g., an array consisting of elements that all are most-recent holders is considered to be a most-recent holder. The only exception is the role organizer which describes the array as a whole.

Fields of record variables should be treated separately because they may have very different roles. For example, a record may consist of two fields: one for identifying the item that the record describes (presumably a fixed value) and one for collecting data concerning that item (presumably a gatherer).

In procedures and functions, formal value parameters and local variables can be considered to be normal variables. In contrast, formal variable parameters should be unified with the actual parameter because every change made to the parameter (within the procedure or function) contributes to the succession of values that the actual variable goes through.

Finally, file variables behave very differently from other variables: the file variable itself is usually a fixed value, i.e., it denotes the same file throughout the program, but the contents of successive file elements convey a file element role not comparable to other roles.

An introductory article

Last updated: March 31, 2006



Jorma.Sajaniemi@UEF.Fi