COND. The rest of the function consists of enumerating all the possible cases.
The first case should do the simplest work, in a nonrecursive
fashion. For example, 90% of all functions that process a list will
NULL, and deal directly with the empty
For each case after the first, you should notice what the above
(failed) conditions are telling you. For example, if your first
(NULL L), then in the second clause you
L is not the empty list (or you would never
have gotten to the second clause).
Programming in LISP is largely a matter of enumerating all the possible cases and writing a clause to deal with each. In each clause you know that the tests of all the preceding clauses failed, and you write a test to bite off a small section of the possibilities that are left.
Be sure that you always check the arguments of a function for legality
before you call the function with them. For example, don't call
(CAR L) until you know that
L is a nonempty
list. Don't call
(EQ X Y) until you know that
Y are atoms.
Where algorithmic languages use assignment statements, sequential execution of statements, and loops, LISP uses function composition and recursion. Programmers used to an algorithmic language may therefore find LISP to be difficult and confusing. It takes some experience with the language before the beauty of LISP begins to be apparent.
Most implementations of LISP provide constructs similar to those found in algorithmic languages. These are best avoided by the beginning LISP programmer, as they allow the novice to ``write Fortran programs in LISP'' and never fully master the LISP approach to programming.