LEARNING LISP

Contents | How to Save the World | The Conditional

This Thing Called Lambda

All the functions that were defined previously had something called LAMBDA in them. We left this without explanation up to now. Here we'll take a deeper look at the LAMBDA function and what it does.

Functions are always defined in the following form:

(DEFINE (name (LAMBDA (formal arguments) function-expression )))

"Name" is the name of the function being defined. This shouldn't cause any trouble. "Function-expression" is simply the expression that will be evaluated when we invoke the named function. We've been here before, right? When you type "(name . . .)" Lisp evaluates: "(function-expression)". That was how we got FIRST to do a CAR function. Whenever "(first . . .)" was entered, Lisp replaced it with its defined function-expression, "(car . . .)".

"Formal arguments" serve to hold the place for the actual value[s] which will be inserted when the function is evaluated. As you will recall from previous chapters, we had a formal argument [L] in the FIRST function. We couldn't get the value of L outside of the function. The "function-expression" can use L, but we can't! Why is that?

Let's look again at the function FIRST.

(define (first (lambda (L)
(car L) )))
Now, let's invoke FIRST.
:(FIRST '(A B C))

  A
This is the same result we would have gotten if we had instead done
:(SETQ L '(A B C))

  (A B C )

:(CAR L)

  A
except that if we had done that, the value of L would still have been available after the CAR operation. It seems that the formal arguments got SETQed to match the supplied argument when the function was invoked. The only difference is that after the function finishes [that is, the function-expression is done evaluating] the values get unSETQed.

If the function has an error that causes an interrupt [you get an error message and get a "+" prompt], then it hasn't finished evaluation yet, and the values assigned to the formal arguments are still there. That is why we can look at them when we have the "+" prompt. When we tell Lisp to terminate the function that was suspended by entering a NIL to the "+", then it terminates the function and, POOF, the values that were in our formal arguments are gone.

To be a little more specific, the supplied arguments in the calling expression are matched with the formal arguments. Then the values of the supplied arguments are inserted into the function expression where their associated formal arguments were. This is subsequently evaluated in place of the original expression.

Now let's discuss some variations on this theme. If there had been two variables in the formal argument list ["(L m)" for example], then we would have to put two variables in the part of the expression supplied with arguments. It should be pointed out that the names in the formal argument list [also known as the "lambda list"] are completely arbitrary. "L" and "M" might just as easily have been "LOVESICK" and "MOOSE", as long as we did the same in the function-expression also.

As an example of a two-argument function, here is a function that concatenates two lists together. We are calling it MERGE:

:(DEFINE (MERGE (LAMBDA (L M)

:       (CONC L M))))

  MERGE

:(MERGE '(A B C) '(D E F))

  (A B C D E F )
The first supplied argument would be bound [CONC is short for CONCatenate] to the first name "L" and the second would be bound to the name "m".
( (a b c) (d e f) )
-------------------
(    L       m    )

Let's try giving Lisp nothing to connect to the formal argument:

:(FIRST)

    ** ERROR: TOO FEW ARGS **
      FIRST :: NIL

+()

  NIL
Oops! Well, that should have been expected. FIRST had one formal argument and we supplied none, so it told us that we had too few. Now the error reports should be slightly more meaningful to you.

Can you figure out what would happen if we had typed "(first '(a b c '(d e f))"? Try it.

The process of assigning the values of the supplied arguments to the formal arguments is called Lambda-Binding. The arguments in the "lambda-list" [the formal arguments] are called locals. They are "local" to the function in which they are bound in that when the function ends, the binding comes apart, and L [in the case of FIRST] no longer has the value it had inside the function. That is why we can't see the value in L after the function has ended.

The process of Lambda Binding is an important concept in Lisp. We will discuss its mechanisms in detail later on. For the time being it is important that you understand what it appears to do to variables.

Contents | How to Save the World | The Conditional