We have identified in Lisp some of the elements that must appear in any powerful programming language:
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 (+ 2 5))
(square (square 3))
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)
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)))
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.