LEARNING LISP

Help Functions

The functions we defined in preceding chapters used functions such as CAR and CDR. These functions are called built-ins. A built-in function is nothing mysterious. All the built-in functions are just the same as your own functions [like FIRST]. In fact, once you define a function, it becomes built-in until you leave Lisp. The only difference between built-ins that you build in and those that are built in by Lisp is that the latter are defined automatically each time you enter Lisp.

A built-in that you build into Lisp [like FIRST] is called a help function. We call these help-functions because we can use them to write other functions that do bigger and better things. [We could use them to do smaller and worse things, but that isn't any fun.]

Let's write a function called ENDS which takes the first and last elements from a list and returns them as a new list. To begin with, let's redefine FIRST and LAST, since, unless you saved your workspace the last time, they are not there any more.

```:(DEFINE (FIRST (LAMBDA (L)

:      (CAR L))))))

FIRST

:(DEFINE (LAST (LAMBDA (L)

:        (CAR (REVERSE L)))))

LAST
```
Okay, now we define ENDS which uses FIRST and LAST as help-functions.
```:(DEFINE (ENDS (LAMBDA (L)

:        (CONC (FIRST L) (LAST L))))))

ENDS
```
We'll try it out.
```:(SETQ INPUTLIST '(GRATEFUL ARE THOSE WHO

(GRATEFUL ARE THOSE WHO ARE NOT DEAD )

:(ENDS INPUTLIST)

** ERROR: BAD LIST ARG **
CONC :: ((FIRST L ) (LAST L ) )

+L

(GRATEFUL ARE THOSE WHO ARE NOT DEAD )

+(FIRST L)

GRATEFUL

+(LAST L)

+()

NIL

:(FIRST L)

** ERROR: UNDEFINED ATOM **
EVAL :: L

+()

NIL
```
When Lisp comes back with the "+" prompt, then the function we are executing [which was ENDS] is suspended. This means that it has been stopped in mid-evaluation due to some error. At this time, the formal argument "L" has the value intact. We can look at its value and also use it in other functions while ENDS is still suspended. You know ENDS is still suspended because you still get the "+" prompt. After you type the "()", the suspension is cleared, and the formal argument is gone. Let's look at the error report to see if we can find the problem with ENDS. Both FIRST and LAST successfully return values, so they are not the problem. Aha!! CONC takes as arguments two lists, not two atoms! The following is an example:
```:(CONC 'GRATEFUL 'DEAD)

** ERROR: BAD LIST ARG **
CONC :: ((QUOTE GRATEFUL ) (QUOTE

+()

NIL
```
It looks like we'll have to figure out some way of making a list with the results of FIRST and LAST.

How can we make an atom into a list? Think about what CONC does to the parentheses and about what we want the result to look like. Given "anatom" we want to see "(anatom)". We learned that the CONS function puts something into the beginning of a list. We can simply use CONS to put the atom into a NIL list. Do you see that this will give us the result that we need? If not, try it in Lisp.

Now that we have figured out what the problem was, how do we fix up poor old ENDS? Why not write another help-function called MAKELIST that puts parentheses around the result of FIRST and LAST for us.

```:(DEFINE (MAKELIST (LAMBDA (ATOM)

:        (CONS ATOM NIL))))

MAKELIST
```
Try it out.
```:(MAKELIST 'DEADHEAD)

```
Okay, that looks good. Now all we have to do is change ENDS to use MAKELIST as a help-function. [Note the proliferation of help-functions. It's better to have a lot of help-functions than not enough.]
```:(DEFINE (ENDS (LAMBDA (L)

:   (CONC (MAKELIST (FIRST L)) (MAKELIST

:(LAST L))))))))

ENDS

:(ENDS '( I CANT BELIEVE I ATE THE WHOLE

:THINK)))

(I THINK )

:(ENDS INPUTLIST)