## 1.1.4 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 abstration.
• 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:

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. 12

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. 13 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. 14 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.