    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, x2 +y2 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