** Next:** The Substitution Model for
** Up:** The Elements of Programming
** Previous:** Evaluating Combinations

##

Compound Procedures

We have identified in Lisp some of the elements that must appear in
any powerful programming language:

- Numbers and arithmetic operations are
primitive data and procedures.

- Nesting of combinations provides a means of
combining operations.

- Definitions that associate names with values provide a
limited means of abstraction.

Now we will learn about
*procedure definitions*, a much more powerful abstraction
technique by which a compound operation can be given a name and then
referred to as a unit.

We begin by examining how to express the idea of ``squaring.'' We
might say, ``To square something, multiply it by itself.'' This is
expressed in our language as

(define (square x) (* x x))

We can understand this in the following way:

(define (square x) (* x x))
To square something, multiply it by itself.

We have here a *compound procedure*, which has been given the name
`square`. The procedure represents the operation of multiplying
something by itself. The thing to be multiplied is given a local
name, `x`, which plays the same role that a pronoun plays in
natural language.
Evaluating the definition creates this
compound procedure and associates it with the name `
square`.^{}
The general form of a procedure definition is

(define (name formal parameters) body)

The name is a symbol to be associated with the procedure
definition in the environment.^{}
The
formal parameters are
the names used within the body of the procedure to refer to the
corresponding arguments of the procedure. The
body is an expression that will yield the value of
the procedure application when the formal parameters are replaced by
the actual arguments to which the procedure is applied.^{}
The name
and the formal parameters
are grouped within
parentheses, just as they
would be in an actual call to the procedure being defined.
Having defined `square`, we can now use it:

(square 21)
441
(square (+ 2 5))
49

(square (square 3))
81

We can also use `square` as a building block in defining other
procedures. For example, *x*^{2} +*y*^{2} can be expressed as

(+ (square x) (square y))

We can easily define a procedure
`sum-of-squares` that, given any two numbers as arguments, produces the
sum of their squares:

(define (sum-of-squares x y)
(+ (square x) (square y)))
(sum-of-squares 3 4)
25

Now we can use `sum-of-squares` as a building block in constructing
further procedures:

(define (f a)
(sum-of-squares (+ a 1) (* a 2)))
(f 5)
136

Compound procedures are used in exactly the same way as primitive
procedures. Indeed, one could not tell by looking at the definition
of `sum-of-squares` given above whether `square` was built into
the interpreter, like `+` and `*`, or defined as a compound procedure.

** Next:** The Substitution Model for
** Up:** The Elements of Programming
** Previous:** Evaluating Combinations
*Ryan Bender*

*2000-04-17*