A critical aspect of a programming language is the means it provides for using names to refer to computational objects. We say that the name identifies a variable whose value is the object.
In the Scheme dialect of Lisp, we
name things with
(define size 2)
causes the interpreter to associate the value 2 with the name size. Once the name size has been associated with the number 2, we can refer to the value 2 by name:
(* 5 size)10
Here are further examples of the use of
(define pi 3.14159) (define radius 10) (* pi (* radius radius))314.159
(define circumference (* 2 pi radius)) circumference62.8318
Define is our language’s
simplest means of abstraction, for it allows us to use simple names to
refer to the results of compound operations, such as the
circumference computed above.
In general, computational objects may have very complex
structures, and it would be extremely inconvenient to have to remember
and repeat their details each time we want to use them. Indeed,
complex programs are constructed by building, step by step,
computational objects of increasing complexity. The
interpreter makes this step-by-step program construction particularly
convenient because name-object associations can be created
incrementally in successive interactions. This feature encourages the incremental development and testing of programs and is largely
responsible for the fact that a Lisp program usually consists of a large
number of relatively simple procedures.
It should be clear that the possibility of associating values with symbols and later retrieving them means that the interpreter must maintain some sort of memory that keeps track of the name-object pairs. This memory is called the environment (more precisely the global environment, since we will see later that a computation may involve a number of different environments).