Lisp Learning Note

PROG1, PROG2, PROGN

These forms are used infrequently today. They were important in earlier
versions of Lisp, in which the body of a function could contain at most one
expression and a COND clause could contain at most one consequent.

One place where PROGN is still useful is in the true-part and false-part of
an IF
=============
Here’s an example where RETURN-FROM is needed, that does not
involve iteration. The function SQUARE-LIST uses MAPCAR to square a
list of numbers. However, if any of the elements turns out not to be a number,
SQUARE-LIST returns the symbol NOPE instead of getting an error. The
RETURN-FROM inside the lambda expression exits not only the lambda
expression, but also the MAPCAR, and the body of SQUARE-LIST itself.
(defun square-list (x)
(mapcar
#’(lambda (e)
(if (numberp e)
(* e e)
(return-from square-list ’nope)))
x))
(square-list ’(1 2 3 4 5)) => (1 4 9 16 25)
(square-list ’(1 2 three four 5)) => NOPE

chapter 11
Both COUNT-SLICES and FACT have empty bodies. This is often the
most compelling reason to use DO. You can make the assignments implicit by
doing all the work in update expressions in the variable list, so you never have
to write a PUSH or SETF. Functions written in this style are considered very
elegant.
=============
tell the difference of following predicate:

numberp, zerop, evenp, oddp
symbolp null
consp
atom
listp
stringp

atom <-> listp
symbolp <-> numberp
------------------

find the max value of array

(reduce #'max '(7 5 32 9 18 6))
-------------------
Lambda expressions look similar to DEFUNs, except that the function
name is missing and the word LAMBDA appears in place of DEFUN

difference between '(a b) and '(a . b)
(car '(a b)) => a
(car '(a . b)) => a

but
(cdr '(a b)) => (b)
(cdr '(a . b)) => b

-----------------
(defun my-set-equal(x y)
 (and (subsetp x y) (subset y x)))
-----------------
(defun my-subsetp(x y)
 (not (set-difference x y)))
----------------
(defun my-last(x)
(let ((i (car (last x))))
     (if (atom i)
  i
  (my-last i))))
---------------
(defun my-apply (x y)
 (eval (cons x y)))

(my-apply '+ '(1 2)) => 3
(my-apply 'cons '(a (b c))) => Error ! not very like apply
(apply #'cons '(a (b c))) => (a b c)

note:
(my-apply 'A '(B))  => (A B) [directly under interpreter]
---------------
· EQ is the fastest equality test: It compares addresses. Experts use
it to compare symbols quickly, and to test whether two cons cells
are physically the same object. It should not be used to compare
numbers.
· EQL is like EQ except it can safely compare numbers of the same
type, such as two integers or two floating point numbers. It is the
default equality test in Common Lisp.
· EQUAL is the predicate beginners should use. It compares lists
element by element; otherwise it works like EQL.
· EQUALP is more liberal than EQUAL: It ignores case distinctions
in strings, among other things. can compare 2 structs
· = is the most efficient way to compare numbers, and the only way
to compare numbers of disparate types, such as 3 and 3.0. It only
accepts numbers.
=======
setf stand for "set field"
>>>>>>>>>>>>>>>>>>>>>>>>>>
(progn (stmt1 ..) (stmt2 ..) )  <==> (let ( (var..)) (stmt1 ...) stmt2 ...))

>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
(a b . c)  why end with c, In C language, suppose we have the following sturct

struct elem
{
 value val;
 elem* next;
}

the next pointer should always have a value(default is NULL), a elem can not only stand by value;

>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
' means do not evaluate

>>>>>>>>>>>>>>>>>>>>>>>>>>
--------------------------------
dotted pair and proper list
------------------------------
in 2.11 CONS
The CONS function creates cons cells. It takes two inputs and returns a
pointer to a new cons cell whose CAR points to the first input and whose CDR
points to the second. The term ‘‘CONS’’ is short for CONStruct.
------------------------------------
(setf var (cons 'a 'b)) => (a . b)
(setf var2 (list 'a 'b)) => (a b)

(rest (rest var)) => Error: b is not a list
(rest (rest var2)) => nil

--------------------------------------------
When we append the list (A B C) to the list (D E),
APPEND copies the first input but not the second. It makes the cdr of the last
cell of the copy point to the second input, and returns a pointer to the copy, as
shown in Figure 6-1.
This description of how APPEND really works also explains why it is an
error for the first input to APPEND to be a non-list, but it’s okay if the second
input is a non-list.
(append ’a ’(b c d)) => Error! A is not a list.
(append ’(w x y) ’z) => (W X Y . Z)

APPEND wants to copy the cons cells that make up its first input. It can’t
when the first input is A because that isn’t a list, so it signals an error. But
when we append (W X Y) to Z, APPEND can copy its first input and make the
cdr of the last cell point to the second input, so it doesn’t have to signal an
error. In this case the second input is Z rather than a list, so the result looks
odd because the cons cell chain doesn’t end in NIL.
Let us now return to the problem of adding an element to the end of a list.
If we first make a list of the element, we can solve this problem by using
APPEND.
(append ’(a b c) ’(d)) => (A B C D) ; can not use (append '(a b c) (list d)), d is not a variable
>>>>>>>>>>>>>>>>>>>>>
(defun add-to-end (x e)
"Adds element E to the end of list X."
(append x (list e)))   ; can not use 'e
(add-to-end ’(a b c) ’d) => (A B C D)
>>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>
1.3 THREE KINDS OF NUMBERS
In this book we will work mostly with integers, which are whole numbers.
Common Lisp provides many other kinds of numbers. One kind you should
know about is floating point numbers. A floating point number is always
written with a decimal point; for example, the number five would be written
5.0. The SQRT function generally returns a floating point number as its result,
even when its input is an integer.

Ratios are yet another kind of number. On a pocket calculator, one-half
must be written in floating point notation, as 0.5, but in Common Lisp we can
also write one-half as the ratio 1/2. Common Lisp automatically simplifies
ratios to use the smallest possible denominator; for example, the ratios 4/6,
6/9, and 10/15 would all be simplified to 2/3.
When we call an arithmetic function with integer inputs, Common Lisp
will usually produce an integer or ratio result. If we use a mixture of integers
and floating point numbers, the result will be a floating point number:

1.5 SYMBOLS
Symbols are another type of data in Lisp. Most people find them more
interesting than numbers. Symbols are typically named after English words
(such as TUESDAY), or phrases (e.g., BUFFALO-BREATH), or common
abbreviations (like SQRT for ‘‘square root.’’) Symbol names may contain
practically any combination of letters and numbers, plus some special
characters such as hyphens. Here are some examples of Lisp symbols:
X ZORCH
BANANAS R2D2
COMPUTER WINDOW-WASHER
LORETTA WARP-ENGINES
ABS GARBANZO-BEANS
YEAR-TO-DATE BEEBOP
and even
ANTIDISESTABLISHMENTARIANISM

Notice that symbols may include digits in their names, as in ‘‘R2D2,’’ but
this does not make them numbers. It is important that you be able to tell the
difference between numbers—especially integers—and symbols. These
definitions should help:
integer A sequence of digits ‘‘0’’ through ‘‘9,’’ optionally
preceded by a plus or minus sign.
symbol Any sequence of letters, digits, and permissible
special characters that is not a number.
So FOUR is a symbol, 4 is an integer, + 4 is an integer, but + is a symbol. And
7-11 is also a symbol

1.6 THE SPECIAL SYMBOLS T AND NIL
Two Lisp symbols have special meanings attached to them. They are:
T Truth, ‘‘yes’’
NIL Falsity, emptiness, ‘‘no’’

T and NIL are so basic to Lisp that if you ask a really dedicated Lisp
programmer a yes-or-no question, he may answer with T or NIL instead of
English. (‘‘Hey, Jack, want to go to dinner?’’ ‘‘NIL. I just ate.’’) More
importantly, certain Lisp functions answer questions with T or NIL. Such
yes-or-no functions are called predicates.

1.7 SOME SIMPLE PREDICATES
A predicate is a question-answering function. Predicates output the symbol T
when they mean yes and the symbol NIL when they mean no. The first
predicate we will study is the one that tests whether its input is a number or
not. It is called NUMBERP (pronounced ‘‘number-pee,’’ as in ‘‘number
predicate’’).

2.1 LISTS ARE THE MOST VERSATILE DATA TYPE
The name ‘‘Lisp’’ is an acronym for List Processor. Even though the
language has matured in many ways over the years, lists remain its central data
type. Lists are important because they can be made to represent practically
anything: sets, tables, and graphs, and even English sentences. Functions can
also be represented as lists, but we’ll save that topic for the next chapter.

2.2 WHAT DO LISTS LOOK LIKE?
Every list has two forms: a printed representation and an internal one. The
printed representation is most convenient for people to use, because it’s
compact and easy to type on a computer keyboard. The internal representation
is the way the list actually exists in the computer’s memory. We will use a
graphical notation when we want to refer to lists in their internal form.
In its printed form, a list is a bunch of items enclosed in parentheses.
These items are called the elements of the list. Here are some examples of
lists written in parenthesis notation:
(RED GREEN BLUE)
(AARDVARK)

(2 3 5 7 11 13 17)
(3 FRENCH HENS 2 TURTLE DOVES 1 PARTRIDGE
1 PEAR TREE)
The internal representation of lists does not involve parentheses. Inside the
computer’s memory, lists are organized as chains of cons cells, which we’ll
draw as boxes. The cons cells are linked together by pointers, which we’ll
draw as arrows. Each cons cell has two pointers. One of them always points
to an element of the list, such as RED, while the other points to the next cons
cell in the chain.* When we say ‘‘lists may include symbols or numbers as
elements,’’ what we are really saying is that cons cells may contain pointers to
symbols or numbers, as well as pointers to other cons cells. The computer’s
internal representation of the list (RED GREEN BLUE) is drawn this way:**
===========================
RED GREEN BLUE
NIL
========================
Looking at the rightmost cell, you’ll note that the cons cell chain ends in
NIL. This is a convention in Lisp. It may be violated in some circumstances,
but most of the time lists will end in NIL. When the list is written in
parenthesis notation, the NIL at the end of the chain is omitted, again by
convention.

2.3 LISTS OF ONE ELEMENT
A symbol and a list of one element are not the same. Consider the list
(AARDVARK) shown below; it is represented by a cons cell. One of the cons
cell’s pointers points to the symbol AARDVARK; the other points to NIL. So
you see that the list (AARDVARK) and the symbol AARDVARK are
different objects. The former is a cons cell that points to the latter.
==============
AARDVARK
================

2.4 NESTED LISTS
A list may contain other lists as elements. Given the three lists
(BLUE SKY)
(GREEN GRASS)
(BROWN EARTH)
we can make a list of them by enclosing them within another pair of
parentheses. The result is shown below. Note the importance of having two
levels of parentheses: This is a list of three lists, not a list of six symbols.
((BLUE SKY) (GREEN GRASS) (BROWN EARTH))
We can display the three elements of this list vertically instead of
horizontally if we choose. Spacing and indentation don’t matter as long as the
elements themselves and the parenthesization aren’t changed. For example,
the list of three lists could have been written like this:
((BLUE SKY)
(GREEN GRASS)
(BROWN EARTH))
The first element of this list is still (BLUE SKY). In cons cell notation, the
list would be written as shown below. Since it has three elements, there are
three cons cells in the top-level chain. Since each element is a list of two
symbols, each top-level cell points to a lower-level chain of two cons cells.
==============================
BLUE SKY
NIL
GREEN GRASS
NIL
BROWN EARTH
NIL
NIL
Lists that contain other lists are called nested lists. In parenthesis notation,
a nested list has one or more sets of parentheses nested within the outermost
pair. In cons cell notation, a nested list has at least one level of cons cells
below the top-level chain. Lists that are not nested are called flat lists. A flat
list has only a top-level cons cell chain
Lists that contain other lists are called nested lists. In parenthesis notation,
a nested list has one or more sets of parentheses nested within the outermost
pair. In cons cell notation, a nested list has at least one level of cons cells
below the top-level chain. Lists that are not nested are called flat lists. A flat
list has only a top-level cons cell chain.
Lists aren’t always uniform in shape. Here’s a nested list whose elements
are a list, a symbol, and a list:
((BRAIN SURGEONS) NEVER (SAY OOPS))

You can see the pattern of parenthesization reflected in the cons cell
diagram below.
BRAIN SURGEONS
NIL
NEVER
SAY OOPS
NIL
NIL
Anything we write in parenthesis notation will have an equivalent
description inside the computer as a cons cell structure—if the parentheses
balance properly. If they don’t balance, as in the malformed expression
‘‘(RED (GREEN BLUE,’’ the computer cannot make a cons cell chain
corresponding to that expression. The computer will respond with an error
message if it reads an expression with unbalanced parentheses.

2.5 LENGTH OF LISTS
The length of a list is the number of elements it has, for example, the list (HI
MOM) is of length two. But what about lists of lists? When a list is written in
parenthesis notation, its elements are the things that appear inside only one
level of parentheses. For example, the elements of the list (A (B C) D) are A,
the list (B C), and D. The symbols B and C are not elements themselves, they
are merely components of the element (B C).

2.6 NIL: THE EMPTY LIST
A list of zero elements is called an empty list. It has no cons cells. It is
written as an empty pair of parentheses:
()
Inside the computer the empty list is represented by the symbol NIL. This
is a tricky point: the symbol NIL is the empty list; that’s why it is used to mark
the end of a cons cell chain. Since NIL and the empty list are identical, we are
always free to write NIL instead of ( ), and vice versa. Thus (A NIL B) can
also be written (A ( ) B). It makes no difference which printed form is used;
inside the computer the two are the same.

The length of the empty list is zero. Even though NIL is a symbol, it is still
a valid input to LENGTH because NIL is also a list. NIL is the only thing that
is both a symbol and a list.

2.10 CAR AND CDR
By now you know that each half of a cons cell points to something. The two
halves have obscure names. The left half is called the CAR, and the right half
is called the CDR (pronounced ‘‘cou-der,’’ rhymes with ‘‘good-er’’). These
names are relics from the early days of computing, when Lisp first ran on a
machine called the IBM 704. The 704 was so primitive it didn’t even have
transistors—it used vacuum tubes. Each of its ‘‘registers’’ was divided into
several components, two of which were the address portion and the decrement

portion. Back then, the name CAR stood for Contents of Address portion of
Register, and CDR stood for Contents of Decrement portion of Register. Even
though these terms don’t apply to modern computer hardware, Common Lisp
still uses the acronyms CAR and CDR when referring to cons cells, partly for
historical reasons, and partly because these names can be composed to form
longer names such as CADR and CDDAR, as you will see shortly.
Besides naming the two halves of a cons cell, CAR and CDR are also the
names of built-in Lisp functions that return whatever pointer is in the CAR or
CDR half of the cell, respectively. Consider again the list (THE BIG
BOPPER). When this list is used as input to a function such as CAR, what the
function actually receives is not the list itself, but rather a pointer to the first
cons cell:

2.10.4 CAR and CDR of NIL
Here is another interesting fact about NIL: The CAR and CDR of NIL are
defined to be NIL.

2.11 CONS
The CONS function creates cons cells. It takes two inputs and returns a
pointer to a new cons cell whose CAR points to the first input and whose CDR
points to the second. The term ‘‘CONS’’ is short for CONStruct.
If we try to explain CONS using parenthesis notation, we might say that
CONS adds an element to the front of a list. For example, we can add the
symbol A to the front of the list (B C D):

2.11.2 Building Nested Lists With CONS
Any time the first input to CONS is a nonempty list, the result will be a nested
list, that is, a list with more than one level of cons cells

2.13 LIST
Creating a list from a bunch of elements is such a common operation that Lisp
has a built-in function to do just that. The LIST function takes any number of
inputs and makes a list of them.
In parenthesis notation, it
appears to throw a pair of parentheses around its inputs, however many there
are.

(cons 'zort nil) => (zort)
(list 'zort nil) => (zort nil)

(cons 'able '(baker charlie)) => (able baker charlie)
(list 'able '(baker charlie)) => (able (baker charlie))

2.15 LIST PREDICATES
The CONSP predicate returns T if its input is a cons cell. CONSP is
almost the same as LISTP; the difference is in their treatment of NIL. NIL is a
list, but it is not a cons cell.
The ATOM predicate returns T if its input is anything other than a cons
cell. ATOM and CONSP are opposites; when one returns T, the other always
returns NIL.
The word ‘‘atom’’ comes from the Greek atomos, meaning indivisible.
Numbers and symbols are atomic because they cannot be taken apart.
Nonempty lists aren’t atomic: FIRST and REST take them apart.
The NULL predicate returns T if its input is NIL. Its behavior is the same
as the NOT predicate. By convention, Lisp programmers reserve NOT for
logical operations: changing true to false and false to true. They use NULL
when they want to test whether a list is empty.

2.17 NONLIST CONS STRUCTURES
A proper list is a cons cell chain ending in NIL. The convention is to omit
this NIL when writing lists in parenthesis notation, so the structure below is
written (A B C).
A B C
NIL
There are other sorts of cons cell structures that are not proper lists,
because their chains do not end in NIL. How can the structure below be
represented in parenthesis notation?
A B C
D
When printing a list in parenthesis notation, Lisp starts by printing a left
parenthesis followed by all the elements, separated by spaces. Then, if the list
ends in NIL, Lisp prints a right parenthesis. If it does not end in NIL, before
printing the right parenthesis Lisp prints a space, a period, another space, and
the atom that ends the chain. The list above, which is called a dotted list
rather than a proper list, is written like this:
(A B C . D)
So far, the only way we have to produce a cons cell structure that doesn’t
end in NIL is to use CONS.
The result of the CONS of A and B is called a dotted pair. It is written
(A . B) in parenthesis notation, while in cons cell notation it looks like this:
=========    important griphic
A
B

A dotted pair is a single cons cell whose CDR is not NIL. The dotted list
(A B . C) contains two cons cells, and is constructed this way:

Although LIST is often a more convenient tool than CONS for
constructing lists, the LIST function can only build proper lists, since it always
constructs a chain ending in NIL. For dotted lists CONS must be used.

2.18 CIRCULAR LISTS
Dotted lists may look a bit strange, but even stranger structures are possible.
For example, here is a circular list:
A B C
If the computer tried to display this list in printed form, one of several
things might happen, depending on the setting of certain printer parameters
that will be discussed later. The computer could go into an infinite loop. Or it
might try to print part of the list, using ellipsis (three dots), as in:
(A B C A B C A B ...)
This way of writing the list is incorrect, because it suggests that the list
contains more than ten elements, when in fact it contains only three.
Common Lisp does provide a completely correct way to print circular
structures, using something called ‘‘sharp-equal notation,’’ based on the #
(sharp-sign) character. Essentially, to write circular structures we need a way
to assign a label to a cons cell so we can refer back to it later. (For example, in
the circular list above, the CDR of the third cons cell refers back to the first
cell.) We will use integers for labels, and the notation #n= to label an object.
We’ll write #n# to refer to the object later on in the expression. The list above
is therefore written this way:
#1=(A B C . #1#)

2.19 LENGTH OF NONLIST CONS STRUCTURES
The LENGTH of a list is the number of top-level cons cells in the chain.
Therefore the length of (A B C . D) is 3, not 4. It is the same length as the
chain (A B C), which can also be written (A B C . NIL).

If given a circular list such as #1=(A B C . #1#) as input, LENGTH may
not return a value at all. In most implementations it will go into an infinite
loop.

3.1 INTRODUCTION EVAL Notation
Before progressing further in our study of Lisp, we must switch to a more
flexible notation, called EVAL notation. Instead of using boxes to represent
functions, we will use lists. Box notation is easy to read, but EVAL notation
has several advantages:
· Programming concepts that are too sophisticated to express in box
notation can be expressed in EVAL notation.
· EVAL notation is easy to type on a computer keyboard; box
notation is not.
· From a mathematical standpoint, representing functions as
ordinary lists is an elegant thing to do, because then we can use
exactly the same notation for functions as for data.
· In Lisp, functions are data, and EVAL notation allows us to write
functions that accept other functions as inputs. We’ll explore this
possibility further in chapter 7.
· When you have mastered EVAL notation, you will know most of
what you need to begin conversing in Lisp with a computer.

3.2 THE EVAL FUNCTION
The EVAL function is the heart of Lisp. EVAL’s job is to evaluate Lisp
expressions to compute their result. Most expressions consist of a function
followed by a set of inputs. If we give EVAL the expression (+ 2 3), for
example, it will invoke the built-in function + on the inputs 2 and 3, and + will
return 5. We therefore say the expression (+ 2 3) evaluates to 5.

It should be obvious that any expression we write in box notation can also be
written in EVAL notation.

3.4 EVALUATION RULES DEFINE THE BEHAVIOR OF EVAL
1)=================================================================
Evaluation Rule for Numbers, T, and NIL: Numbers, and the symbols T
and NIL, evaluate to themselves.
2)===========================================================
Evaluation Rule for Lists: The first element of the list specifies a
function to be called. The remaining elements specify arguments to the
function. The function is called on the evaluated arguments.

3.5 DEFINING FUNCTIONS IN EVAL NOTATION
In box notation we defined a function by showing what went on inside the
box. The inputs to the function were depicted as arrows, In EVAL notation
we use lists to define functions, and we refer to the function’s arguments by
giving them names. We can name the inputs to box notation functions too, by
writing the name next to the arrow like this:

The AVERAGE function is defined in EVAL notation this way:
(defun average (x y)
(/ (+ x y) 2.0))
DEFUN is a special kind of function, called a macro function, that does
not evaluate its arguments. Therefore they do not have to be quoted. DEFUN
is used to define other functions. The first input to DEFUN is the name of the
function being defined. The second input is the argument list: It specifies the
names the function will use to refer to its arguments. The remaining inputs to
DEFUN define the body of the function: what goes on ‘‘inside the box.’’ By
the way, DEFUN stands for define function.

Almost any symbol except T or NIL can serve as the name of an argument.
X, Y, and N are commonly used, but BOZO or ARTICHOKE would also
work.

3.6 VARIABLES
A variable is a place where data is stored.* Let’s consider the AVERAGE
function again. When we call AVERAGE, Lisp creates two new variables to
hold the inputs so that the expression in the body can refer to them by name.
The names of the variables are X and Y. It is important to distinguish here
between variables and symbols. Variables are not symbols; variables are
named by symbols. Functions are also named by symbols.
The value of a variable is the data it holds. When we evaluate (AVERAGE
3 7), Lisp creates variables named X and Y and assigns them the values 3 and
7, respectively. In the body of AVERAGE, the symbol X refers to the first
variable and the symbol Y refers to the second. These variables can only be
referenced inside the body; outside of AVERAGE they are inaccessible. Of
course the symbols X and Y still exist outside of AVERAGE, but they don’t
have the same meanings outside as they have inside. The evaltrace diagram
below shows how AVERAGE computes its result.
(average 3 7)
3 evaluates to 3
7 evaluates to 7
Enter AVERAGE with inputs 3 and 7
create variable X, with value 3
create variable Y, with value 7
(/ (+ x y) 2.0)
(+ x y)
X evaluates to 3
Y evaluates to 7
10
2.0 evaluates to 2.0
5.0
Result of AVERAGE is 5.0
*This use of the term ‘‘variable’’ is peculiar to computer programming. In mathematics, a variable is

a
notation for an unknown quantity, not a physical place in computer memory. But these two meanings are
not incompatible, since the inputs to a function are in fact unknown quantities at the time the function

is
defined.

3.7 EVALUATING SYMBOLS
The names a function uses for its arguments are independent of the names any
other function uses. Two functions such as HALF and SQUARE might both
call their argument N, but when N appears in HALF it can only refer to the
input of HALF; it has no relation to the use of N in SQUARE.
The rule EVAL uses for evaluating symbols is simple:

======================================
Evaluation Rule for Symbols: A symbol evaluates to the value of the
variable it refers to.

Outside the bodies of HALF and SQUARE, the symbol N refers to the
global variable named N. A global variable is one that is not associated with
any function. PI is an example of a global variable that is built in to Common
Lisp.

Informally, Lisp programmers sometimes talk of evaluating variables.
They might say ‘‘variables evaluate to their values.’’ What they really mean
is that a symbol evaluates to the value of the variable it refers to. Since there
can be many variables named N, which one you get depends on where the
symbol N appears. If it appears inside the body of SQUARE, you get the
variable that holds the input to SQUARE. If it appears outside of any
function, you get the global variable named N.

3.8 USING SYMBOLS AND LISTS AS DATA
Suppose we want to call EQUAL on the symbols KIRK and SPOCK. In box
notation this was easy, because symbols and lists were always treated as data.
But in EVAL notation symbols are used to name variables, so if we write
(equal kirk spock)
Lisp will think we are trying to compare the value of the global variable
named KIRK with the value of the global variable named SPOCK. Since we
haven’t given any values to these variables, this will cause an error:
(equal kirk spock) T Error! KIRK unassigned variable.
What we really want to do is compare the symbols themselves. We can tell
Lisp to treat KIRK and SPOCK as data rather than as variable references by
putting a quote before each one.
(equal ’kirk ’spock) => nil
Because the symbols T and NIL evaluate to themselves, they don’t need to be
quoted to use them as data. Most other symbols do, though.
(list ’james t ’kirk) => (james t kirk)
Whether symbols are used as data in a function definition, or are passed as
inputs when the function is called, they must be quoted to prevent evaluation.
(defun riddle (x y)
(list ’why ’is ’a x ’like ’a y))
(riddle ’raven ’writing-desk) =>
(why is a raven like a writing-desk)
Lists also need to be quoted to use them as data; otherwise Lisp will try to
evaluate them, which typically results in an ‘‘undefined function’’ error.
(first (we hold these truths))
T Error! WE undefined function.
(first ’(we hold these truths)) => we

=====================================
Evaluation Rule for Quoted Objects: A quoted object evaluates to the
object itself, without the quote.

3.9 THE PROBLEM OF MISQUOTING
It is easy for beginning Lisp programmers to get confused about quoting and
either put quotes in the wrong place or leave them out where they are needed.
The error messages Lisp gives are a good hint about what went wrong. An
unassigned variable or undefined function error usually indicates that a quote
was left out:
(list ’a ’b c) => Error! C unassigned variable.
(list ’a ’b ’c) => (a b c)
(cons ’a (b c)) => Error! B undefined function.
(cons ’a ’(b c)) => (a b c)
On the other hand, wrong-type input errors or funny results may be an
indication that a quote was put in where it doesn’t belong.
(+ 10 ’(- 5 2)) => Error! Wrong type input to +.
(+ 10 (- 5 2)) => 13
(list ’buy ’(* 27 34) ’bagels)
=> (buy (* 27 34) bagels)
(list ’buy (* 27 34) ’bagels)
=> (buy 918 bagels)

When we quote a list, the quote must go outside the list to prevent the list
from being evaluated. If we put the quote inside the list, EVAL will try to
evaluate the list and an error will result:
(’foo ’bar ’baz) T Error! ’FOO undefined function.
’(foo bar baz) T (foo bar baz)

One advantage of building the list up from individual elements is that some of
the elements can be computed rather than specified directly.

(list 33 ’squared ’is (* 33 33))
=> (33 squared is 1089)
If we quote a list, nothing inside it will get evaluated:
’(33 squared is (* 33 33))
=> (33 squared is (* 33 33))
We have seen several ways things can go wrong if quotes are not used
properly when building a list:
(list foo bar baz) => Error! FOO unassigned variable.
(foo bar baz) => Error! FOO undefined function.
(’foo ’bar ’baz) => Error! ’FOO undefined function.

3.11 FOUR WAYS TO MISDEFINE A FUNCTION
Beginning users of EVAL notation sometimes have trouble writing
syntactically correct function definitions. Let’s take a close look at a proper
definition for the function INTRO:
(defun intro (x y) (list x ’this ’is y))
(intro ’stanley ’livingstone) =>
(stanley this is livingstone)
Notice that INTRO’s argument list consists of two symbols, X and Y, with
neither quotes nor parentheses around them, and the variables X and Y are not
quoted or parenthesized in the body, either.
The first way to misdefine a function is to put something other than plain,
unadorned symbols in the function’s argument list. If we put quotes or extra
levels of parentheses in the argument list, the function won’t work. Beginners
are sometimes tempted to do this when they write a function that is to be
called with a list instead of a symbol as input. This is always a mistake.
(defun intro (’x ’y) bad argument list
(list x ’this ’is y))
(defun intro ((x) (y)) bad argument list
(list x ’this ’is y))
The second way to misdefine a function is to put parentheses around
variables where they appear in the body. Only function calls should have
parentheses around them. Putting parentheses around a variable will cause an
undefined function error:
(defun intro (x y) (list (x) ’this ’is (y)))
(intro ’stanley ’livingstone)
=> Error! X undefined function.
The third way to misdefine a function is to quote a variable. Symbols must
be left unquoted when they refer to variables. Here is an example of what
happens when variables are quoted:
(defun intro (x y) (list ’x ’this ’is ’y))
(intro ’stanley ’livingstone) => (x this is y)
The fourth way to misdefine a function is to not quote something that
should be quoted. In the INTRO function, the symbols X and Y are variables
but THIS and IS are not. If we don’t quote THIS and IS, an unassigned
variable error results.
(defun intro (x y) (list x this is y))
(intro ’stanley ’livingstone)
=> Error! THIS unassigned variable.

3.12 MORE ABOUT VARIABLES
In Lisp, a function creates variables automatically when it is is invoked; they
(usually) go away when the function returns. Consider the DOUBLE function,
which creates a variable named N every time we call it:
(defun double (n) (* n 2))
Outside of DOUBLE, the symbol N refers to the global variable named
N. The global variable N has not been assigned any value, so evaluating N
results in an error.

n => Error! N unassigned variable.
Suppose we evaluate (DOUBLE 3). Inside DOUBLE, the symbol N refers
to a newly created variable that holds the input to DOUBLE, not the global
variable N. The evaltrace diagram below illustrates this.
(double 3)
Enter DOUBLE with input 3
create variable N with value 3
(* n 2)
N evaluates to 3
6
Result of DOUBLE is 6
If we call DOUBLE again, for example, (DOUBLE 8), a brand-new
variable named N will be created with a value of 8. Outside of DOUBLE the
name N still refers to the global variable N, which still has no value.
Now let’s try an example with two variables. Here is a definition for
QUADRUPLE in terms of DOUBLE: Error! N unassigned variable.
Suppose we evaluate (DOUBLE 3). Inside DOUBLE, the symbol N refers
to a newly created variable that holds the input to DOUBLE, not the global
variable N. The evaltrace diagram below illustrates this.
(double 3)
Enter DOUBLE with input 3
create variable N with value 3
(* n 2)
N evaluates to 3
6
Result of DOUBLE is 6
If we call DOUBLE again, for example, (DOUBLE 8), a brand-new
variable named N will be created with a value of 8. Outside of DOUBLE the
name N still refers to the global variable N, which still has no value.
Now let’s try an example with two variables. Here is a definition for
QUADRUPLE in terms of DOUBLE:

3.17 THE QUOTE SPECIAL FUNCTION
QUOTE is a special function: Its input does not get evaluated. The QUOTE
special function simply returns its input. For example:
(quote foo) => foo
(quote (hello world)) => (hello world)
Early versions of Lisp used QUOTE instead of an apostrophe to indicate that
something shouldn’t be evaluated. That is, where we would write
(cons ’up ’(down sideways))
old-style Lisp programmers would write
(cons (quote up) (quote (down sideways)))
Modern Lisp systems use the apostrophe as shorthand for QUOTE.
Internally, however, they convert the apostrophe to QUOTE. We can
demonstrate that this happens by using multiple quotes. The first quote is
stripped away by the evaluation process, but any extra quotes remain.
’foo => foo
’’foo => ’foo also written (quote foo)
(list ’quote ’foo) => (quote foo) also written ’foo
(first ’’foo) => quote
(rest ’’foo) => (foo)
(length ’’foo) => 2
Depending on the version of Lisp your computer runs, you may
occasionally see QUOTE written out instead of in its shorthand form, the
apostrophe.

3.18 INTERNAL STRUCTURE OF SYMBOLS
So far in this book we have been drawing symbols by writing their names.
But symbols in Common Lisp are actually composite objects, meaning they
have several parts to them. Conceptually, a symbol is a block of five pointers,
one of which points to the representation of the symbol’s name. The others
will be defined later. The internal structure of the symbol FRED looks like
this:
=============================      graphic
name "FRED"

The ‘‘FRED’’ appearing above in quotation marks is called a string.
Strings are sequences of characters; they will be covered more fully in Chapter
9. For now it suffices to note that strings are used to store the names of
symbols; a symbol and its name are actually two different things.
Some symbols, like CONS or +, are used to name built-in Lisp functions.
The symbol CONS has a pointer in its function cell to a ‘‘compiled code
object’’ that represents the machine language instructions for creating new
cons cells.
====================== graphic
name
function
"CONS"
Compiled
CONS
Function
======================
When we draw Lisp expressions such as (EQUAL 3 5) as cons cell chains,
we usually write just the name of the symbol instead of showing its internal
structure:
==================== IMPORTANT GRAPICS

3.19 LAMBDA NOTATION
Lambda notation was created by Alonzo Church, a mathematician at Princeton
University. Church wanted a clear, unambiguous way to describe functions,
their inputs, and the computations they perform. In lambda notation, a
function that adds 3 to a number would be written as shown below; the l is the
CHAPTER 3 EVAL Notation 107
Greek letter lambda: lx.(3+x).
John McCarthy, the originator of Lisp, was a student of Church. He
adopted Church’s notation for specifying functions. The Lisp equivalent of
the unnamed function lx.(3+x) is the list
(lambda (x) (+ 3 x))
A function f(x,y) = 3x+y2 would be written l(x,y).(3x+y2) in lambda
notation. In Lisp it is written
(lambda (x y) (+ (* 3 x) (* y y)))
As you can see, the syntax of lambda expressions in Lisp is similar to that of
Church’s notation, and even more similar to DEFUN. But unlike DEFUN,
LAMBDA is not a function; it is a marker treated specially by EVAL. We’ll
learn more about lambda expressions in chapter 7.
======================== IMPORTANT GRAPHICS

Of course, the lambda expression is just a list constructed out of cons cells.
And each of the symbols in the lambda expression, such as N and /, is really a
block of five pointers. Since the symbol / names the division function, it
contains a pointer to a built-in function object for performing division. So,
indirectly, HALF points to the built-in division function. Figure 3-1 shows
these details.

3.21 EVAL AND APPLY
EVAL is a Lisp primitive function. Each use of EVAL gives one level of
evaluation.
’(+ 2 2) => (+ 2 2)
’’’boing => ’’boing

We won’t use EVAL explicitly in any of the programs we write, but we
make implicit use of it all the time. You can think of the computer as a
physical manifestation of EVAL. When it runs Lisp, everything you type is
evaluated.

APPLY is also a Lisp primitive function. APPLY takes a function and a
list of objects as input. It invokes the specified function with those objects as
its inputs. The first argument to APPLY should be quoted with #’ rather than
an ordinary quote; #’ is the proper way to quote functions supplied as inputs
to other functions. This will be explained in more detail in Chapter 7.
(apply #’+ ’(2 3)) => 5
(apply #’equal ’(12 17)) => nil
The objects APPLY passes to the function are not evaluated first. In the
following example, the objects are a symbol and a list. Evaluating either the
symbol AS or the list (YOU LIKE IT) would cause an error.
(apply #’cons ’(as (you like it)))
=> (as you like it)
EVAL and APPLY are related to each other. A popular exercise in more
advanced Lisp texts involves writing each function in terms of the other.

5.10 BINDING, SCOPING, AND ASSIGNMENT
Because Common Lisp evolved from older, less sophisticated Lisp dialects, it
has inherited terminology that in a few cases doesn’t quite fit. This book
strives to use only correct and unambiguous terminology, but for compatibility
with other books and the Lisp community at large, I will digress for a section
and explain the various uses and misuses of the term ‘‘binding.’’
For historical reasons, variables that have values are said to be ‘‘bound,’’
and variables with no value are said to be ‘‘unbound.’’ While this book talks
about ‘‘unassigned variable’’ errors, the error message most Lisp
implementations produce is ‘‘unbound variable.’’
The process of creating a new variable and giving it a value is called
‘‘binding.’’ If the variable appears in a function’s argument list, it is said to be
created by ‘‘lambda binding.’’ If it appears in the variable list of a LET or
LET* form, it is said to be created by ‘‘LET-binding.’’ These uses of
‘‘binding’’ are not incorrect today. A Lisp expert might well say that we
cured the bug in COIN-WITH-BUG ‘‘by LET-binding a variable to the value
of (RANDOM 101).’’
But old-time Lispers get themselves into terminological trouble when they
try to talk about the binding of variables in ways that aren’t true for lexically
scoped Lisps. While variables are lexically scoped by default, Common Lisp
also provides another scoping discipline, called dynamic scoping, which we
won’t get into until Chapter 14. Dynamic scoping was the default in most
earlier Lisp dialects, except for Scheme and T. ‘‘Bound’’ doesn’t necesssarily
mean ‘‘has a value’’ for dynamically scoped variables, because it is possible
for such a variable to be bound but have no value.
Referring to the functions F and G in the preceding section, old-time
Lispers would say ‘‘the symbol A is bound to 3 by F.’’ This is not proper
language if you are speaking about Common Lisp. Symbols are never bound;
only variables can be bound. And there is no unique variable named A; there
are two. Even while F’s local variable A is in existence, the global A can be
referenced by functions such as G whose lexical context is outside the body of
F. To express the offending phrase in correct Common Lisp, one should say
‘‘F binds a local variable A to 3.’’


6.4 COMPARING CONS, LIST, AND APPEND

important

6.9 PROGRAMMING WITH TABLES

p263

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值