about summary refs log tree commit diff stats
path: root/js/games/nluqo.github.io/~bh/ssch27/appendix-cl.html
diff options
context:
space:
mode:
Diffstat (limited to 'js/games/nluqo.github.io/~bh/ssch27/appendix-cl.html')
-rw-r--r--js/games/nluqo.github.io/~bh/ssch27/appendix-cl.html523
1 files changed, 523 insertions, 0 deletions
diff --git a/js/games/nluqo.github.io/~bh/ssch27/appendix-cl.html b/js/games/nluqo.github.io/~bh/ssch27/appendix-cl.html
new file mode 100644
index 0000000..f4dc775
--- /dev/null
+++ b/js/games/nluqo.github.io/~bh/ssch27/appendix-cl.html
@@ -0,0 +1,523 @@
+<P>
+
+<P>
+<HTML>
+<HEAD>
+<TITLE>Simply Scheme Appendix B: Common Lisp</TITLE>
+</HEAD>
+<BODY>
+<CITE>Simply Scheme</CITE>:
+<CITE>Introducing Computer Science</CITE> 2/e Copyright (C) 1999 MIT
+<H2>Appendix B</H2>
+<H1>Common Lisp</H1>
+
+<TABLE width="100%"><TR><TD>
+<IMG SRC="../simply.jpg" ALT="cover photo">
+<TD><TABLE>
+<TR><TD align="right"><CITE><A HREF="http://www.cs.berkeley.edu/~bh/">Brian
+Harvey</A><BR>University of California, Berkeley</CITE>
+<TR><TD align="right"><CITE><A HREF="http://ccrma.stanford.edu/~matt">Matthew
+Wright</A><BR>University of California, Santa Barbara</CITE>
+<TR><TD align="right"><BR>
+<TR><TD align="right"><A HREF="../pdf/ssch27.pdf">Download PDF version</A>
+<TR><TD align="right"><A HREF="../ss-toc2.html">Back to Table of Contents</A>
+<TR><TD align="right"><A HREF="appendix-running.html"><STRONG>BACK</STRONG></A>
+chapter thread <A HREF="appendix-simply.html"><STRONG>NEXT</STRONG></A>
+<TR><TD align="right"><A HREF="http://mitpress.mit.edu/0262082810">MIT
+Press web page for <CITE>Simply Scheme</CITE></A>
+</TABLE></TABLE>
+
+<HR>
+
+<P>The two most popular dialects of Lisp are Scheme and Common Lisp.  This
+appendix, which assumes that you have finished the rest of this book,
+describes the most important differences between Scheme and Common Lisp so
+that you will be able to use Common Lisp if you need to.  Common Lisp is the
+most popular language among Artificial Intelligence researchers, so AI
+courses often use Common Lisp.
+
+<P><H2>Why Common Lisp Exists</H2>
+
+<P>Since the beginning of Lisp, many versions of the language were developed.
+Each dialect reflected different ideas about the most important capabilities
+to include in the language.  This diversity made Lisp an exciting arena for
+research, but it also meant that a Lisp program written for one dialect
+couldn't be used elsewhere.
+
+<P>In 1984, a group of Lisp developers decided to define a version of Lisp that
+would combine the capabilities of all their favorite dialects, so that in
+the future they would all use the same language; thus the name &quot;Common&quot;
+Lisp.  Common Lisp was not the first attempt at a universal Lisp dialect,
+but it was more successful than earlier efforts.  In 1985 a revision of the
+language was begun under the aegis of ANSI, the American National Standards
+Institute.  This ANSI sponsorship gave Common Lisp an official status that
+has contributed to its growing acceptance.
+
+<P>Since Common Lisp was designed by combining the capabilities of many earlier
+dialects, it's an enormous language with nearly 1000 primitives, including
+versions of several programs in this book.  There is a primitive <CODE>sort</CODE>
+procedure, a procedure like <CODE>number-name</CODE> that spells numbers in
+English, and a <CODE>substitute</CODE> procedure identical to the one you wrote in
+an exercise, to name a few.
+
+<P>If you're writing your own programs in Common Lisp, you can ignore all the
+extra features and just use the capabilities you already know from Scheme.
+If you're trying to read someone else's Common Lisp program, we expect that
+you will have to look up many primitive procedures in a reference manual.
+
+<P><H2>Defining Procedures and Variables</H2>
+
+<P>One minor difference between Scheme and Common Lisp is in the way procedures
+are defined.  In Common Lisp,
+
+<P><PRE>(defun square (x)
+  (* x x))
+</PRE>
+
+<P>means the same as Scheme's
+
+<P><PRE>(define (square x)
+  (* x x))
+</PRE>
+
+<P>In Scheme, <CODE>define</CODE> is used both for procedures and for variables whose
+values aren't procedures.  In Common Lisp, procedures are given names by a
+mechanism separate from the general variable mechanism; <CODE>defun</CODE> is only
+for procedures.  To define a variable, use <CODE>defvar</CODE>:
+
+<P><PRE>common-lisp&gt; (defvar x 6)
+6
+
+common-lisp&gt; x
+6
+</PRE>
+
+<P>In Common Lisp, <CODE>defvar</CODE> returns the name of the variable you
+define.  If a variable has already been defined, <CODE>defvar</CODE> will not
+change its value; for that you must use <CODE>setq</CODE>.
+
+<P><H2>The Naming Convention for Predicates</H2>
+
+<P>In Common Lisp, names of predicate procedures end in a &quot;<CODE>p</CODE>&quot; (for
+&quot;predicate&quot;) instead of a question mark.  Unfortunately, this convention
+isn't followed strictly.  For example, Common Lisp's version of the <CODE>null?</CODE> predicate is just &quot;<CODE>null</CODE>,&quot; not &quot;<CODE>nullp</CODE>.&quot;
+
+<P><H2>No Words or Sentences</H2>
+
+<P>We've mentioned that Scheme doesn't really have words and
+sentences built in; neither does Common Lisp.  So none of the following
+procedures have Common Lisp equivalents: <CODE>accumulate</CODE>, <CODE>appearances</CODE>, <CODE>before?</CODE>, <CODE>bf</CODE>, <CODE>bl</CODE>, <CODE>butfirst</CODE>, <CODE>butlast</CODE>, <CODE>count</CODE>, <CODE>empty?</CODE>, <CODE>every</CODE>, <CODE>first</CODE>, <CODE>item</CODE>,
+<CODE>keep</CODE>, <CODE>last</CODE>, <CODE>member?</CODE>, <CODE>se</CODE>, <CODE>sentence</CODE>, <CODE>word</CODE>,
+and <CODE>word?</CODE>.  (Common Lisp does have lists, though, and list-related
+procedures such as <CODE>map</CODE>, <CODE>reduce</CODE>, <CODE>append</CODE>, and so on <EM>do</EM>
+have equivalents.)
+
+<P><H2>True and False</H2>
+
+<P>Common Lisp doesn't have the Boolean values <CODE>#t</CODE> and <CODE>#f</CODE>.
+Instead, it has a single false value, <CODE>nil</CODE>, which is also the empty
+list.
+
+<P><PRE>common-lisp&gt; (= 2 3)
+NIL
+
+common-lisp&gt; (cdr '(one-word-list))
+NIL
+
+common-lisp&gt; '()
+NIL
+</PRE>
+
+<P><CODE>Nil</CODE> is a strange beast in Common Lisp.  It isn't a variable with the
+empty list as its value; it's a special self-evaluating symbol.  There is
+also <CODE>t</CODE>, a self-evaluating symbol with a true value.
+
+<P><PRE>common-lisp&gt; 'nil
+NIL
+
+common-lisp&gt; nil
+NIL
+
+common-lisp&gt; t
+T
+</PRE>
+
+<P>Like Scheme, Common Lisp treats every non-false (i.e., non-<CODE>nil</CODE>) value
+as true.  But be careful; in Common Lisp
+
+<P><PRE>common-lisp&gt; (if (cdr '(one-word-list)) 'yes 'no)
+</PRE>
+
+<P>has the value <CODE>NO</CODE>, because the empty list is <CODE>nil</CODE>.
+
+<P>In Common Lisp's <CODE>cond</CODE>, there is no equivalent to <CODE>else</CODE>; Common
+Lisp programmers instead use <CODE>t</CODE> as the condition for their last clause,
+like this:
+
+<P><PRE>(defun sign (n)
+  (cond ((&gt; n 0) 'positive)
+	((= n 0) 'zero)
+	(t 'negative)))
+</PRE>
+
+<P><H2>Files</H2>
+
+<P>Common Lisp's mechanism for dealing with files is trivially different from
+Scheme's.  What Scheme calls &quot;ports,&quot; Common Lisp calls &quot;streams.&quot; Also,
+there is only one procedure for opening streams; the direction is specified
+this way:
+
+<P><PRE>common-lisp&gt; (defvar out-stream (open &quot;outfile&quot; :direction :output))
+#&lt;OUTPUT STREAM &quot;outfile&quot;>
+
+common-lisp&gt; (close out-stream)
+T
+
+common-lisp&gt; (defvar in-stream (open &quot;infile&quot; :direction :input))
+#&lt;INPUT STREAM &quot;infile&quot;>
+
+common-lisp&gt; (close in-stream)
+T
+</PRE>
+
+<P>Note that the <CODE>close</CODE> procedure closes both input streams and
+output streams.
+
+<P>To <CODE>read</CODE> from an input stream, you must invoke <CODE>read</CODE> with three
+arguments:
+
+<P><PRE>common-lisp&gt; (read stream nil <EM>anything</EM>)
+</PRE>
+
+<P>The <CODE>nil</CODE> indicates that reaching the end of the file should
+not be an error.  If <CODE>read</CODE> does reach the end of the file, instead of
+returning a special end-of-file object it returns its third argument.
+It's possible to choose any value as the indicator for reaching the end
+of the file:
+
+<P><PRE>(let ((next (read stream nil 'xyzzy)))
+  (if (equalp next 'xyzzy)
+      'done
+      (do-something next)))
+</PRE>
+
+<P>It's important to choose an end-of-file indicator that couldn't
+otherwise appear as a value in the file.
+
+<P><H2>Arrays</H2>
+
+<P>In Common Lisp, vectors are just a special case of the multidimensional <EM>array</EM> data type that you invented in Exercise <A HREF="../ssch23/vectors.html#arrays">23.15</A>.  There are quite a
+few differences between Common Lisp arrays and Scheme vectors, none very
+difficult, but too numerous to describe here.  If you need to use arrays,
+read about them in a Common Lisp book.
+
+<P><H2>Equivalents to Scheme Primitives</H2>
+
+<P>Other than the word and sentence procedures, here is a table of the
+Scheme primitives from the table on page <A HREF="appendix-funlist.html#funlist">funlist</A> that have
+different names, slightly different behavior, or do not exist at all
+in Common Lisp.  Scheme procedures not in this list (other than the
+word and sentence ones) can be used identically in Common Lisp.
+
+<P>
+<P><TABLE>
+<TR><TH>Scheme<TH>Common Lisp
+<TR><TD><CODE>align</CODE>
+<TD>Common Lisp's <CODE>format</CODE> primitive has a similar purpose
+<TR><TD><CODE>begin</CODE>
+<TD><CODE>progn</CODE>
+<TR><TD><CODE>boolean?</CODE>
+<TD>Doesn't exist; see the section in this appendix about true and
+false values.
+<TR><TD><CODE>c...r</CODE>
+<TD>The same, but <CODE>(c...r nil)</CODE> is <CODE>nil</CODE> instead
+of an error.
+<TR><TD><CODE>children</CODE>
+<TD>You can use our version from Chapter 18.
+<TR><TD><CODE>close-...-port</CODE>
+<TD><CODE>close</CODE>
+<TR><TD><CODE>close-all-ports</CODE>&nbsp;&nbsp;&nbsp;
+<TD>Doesn't exist.
+<TR><TD><CODE>cond</CODE>
+<TD>The same, except for <CODE>else</CODE>; use <CODE>t</CODE> instead.
+<TR><TD><CODE>datum</CODE>
+<TD>You can use our version from Chapter 18.
+<TR><TD><CODE>define</CODE>
+<TD>Either <CODE>defun</CODE>, for procedure, or
+<CODE>defvar</CODE>, otherwise.
+<TR><TD><CODE>display</CODE>
+<TD><CODE>princ</CODE>
+<TR><TD><CODE>eof-object?</CODE>
+<TD>See the section on files.
+<TR><TD><CODE>equal?</CODE>
+<TD><CODE>equalp</CODE>
+<TR><TD><CODE>even?</CODE>
+<TD><CODE>evenp</CODE>
+<TR><TD><CODE>filter</CODE>
+<TD><CODE>remove-if-not</CODE>
+<TR><TD><CODE>for-each</CODE>
+<TD><CODE>mapc</CODE>
+<TR><TD><CODE>integer?</CODE>
+<TD><CODE>integerp</CODE>
+<TR><TD><CODE>lambda</CODE>
+<TD>Discussed later in this appendix.
+<TR><TD><CODE>list?</CODE>
+<TD><CODE>listp</CODE>, except that <CODE>listp</CODE> also returns true
+for improper lists.
+<TR><TD><CODE>list-ref</CODE>
+<TD><CODE>nth</CODE>, except that the arguments come in reverse order.
+<TR><TD><CODE>list->vector</CODE>
+<TD>See the section about arrays.
+<TR><TD><CODE>make-node</CODE>
+<TD>You can use our version from Chapter 18.
+<TR><TD><CODE>make-vector</CODE>
+<TD>See the section about arrays.
+<TR><TD><CODE>map</CODE>
+<TD><CODE>mapcar</CODE>
+<TR><TD><CODE>newline</CODE>
+<TD><CODE>terpri</CODE>
+<TR><TD><CODE>null?</CODE>
+<TD><CODE>null</CODE>
+<TR><TD><CODE>number?</CODE>
+<TD><CODE>numberp</CODE>
+<TR><TD><CODE>odd?</CODE>
+<TD><CODE>oddp</CODE>
+<TR><TD><CODE>open-...-file</CODE>
+<TD>See the section on files.
+<TR><TD><CODE>procedure?</CODE>
+<TD><CODE>functionp</CODE>
+<TR><TD><CODE>quotient</CODE>
+<TD><CODE>truncate</CODE>
+<TR><TD><CODE>read</CODE>
+<TD>Identical except for end of file.  See the section on files.
+<TR><TD><CODE>read-line</CODE>
+<TD>Doesn't exist.  (Common Lisp's <CODE>read-line</CODE> is like our
+<CODE>read-string</CODE>.)
+<TR><TD><CODE>read-string</CODE>
+<TD><CODE>read-line</CODE>
+<TR><TD><CODE>reduce</CODE>
+<TD>The same, but computes <CODE>(f (f a b) c)</CODE> instead of
+<CODE>(f a (f b c))</CODE>
+<TR><TD><CODE>remainder</CODE>
+<TD><CODE>rem</CODE>
+<TR><TD><CODE>repeated</CODE>
+<TD>Doesn't exist.
+<TR><TD><CODE>show</CODE>
+<TD><CODE>Doesn't exist but easy to write.</CODE>
+<TR><TD><CODE>show-line</CODE>
+<TD><CODE>Doesn't exist.</CODE>
+<TR><TD><CODE>vector-</CODE><I>anything</I>
+<TD>See the section about arrays.
+<TR><TD><CODE>write</CODE>
+<TD><CODE>prin1</CODE>
+</TABLE><P>
+
+
+<P><H2>A Separate Name Space for Procedures</H2>
+
+<P>All of the differences noted in this table are fairly minor ones, in the
+sense that the translation needed to account for these differences requires
+little more than renaming.  There is one major conceptual difference between
+the two languages, however, in the way they treat names of procedures.
+Common Lisp allows a procedure and a variable to have the same name.  For
+example, the program
+
+<P><PRE>(defun three-copies (list)
+  (list list list list))
+</PRE>
+
+<P>is perfectly legal.
+
+<P><PRE>common-lisp&gt; (three-copies '(drive my car))
+((DRIVE MY CAR) (DRIVE MY CAR) (DRIVE MY CAR))
+</PRE>
+
+<P>How can Common Lisp tell that one of the <CODE>list</CODE>s means the primitive
+procedure, but the other ones mean the formal parameter?  Symbols in the
+first position in a list (right after an open parenthesis) are taken
+to be names of globally defined procedures.
+
+<P>In Chapter 7 we introduced the image of a blackboard with all the
+global variables written on it, which all the Scheme little people can see.
+In Common Lisp, there are <EM>two</EM> blackboards: one for global
+variables, just as in Scheme, and another one for procedures.  The procedure
+blackboard contains the primitive procedures and the procedures you define
+with <CODE>defun</CODE>.  Names in the first position of an expression are looked
+up on the procedure blackboard.
+
+<P>Therefore, the names of procedures are not variables and cannot be used as
+actual argument expressions:
+
+<P><PRE>common-lisp&gt; (sqrt 144)
+12
+
+common-lisp&gt; (mapcar sqrt '(9 16 25 36))
+ERROR: The variable SQRT is unbound.
+</PRE>
+
+<P>(Common Lisp's equivalent of <CODE>map</CODE> is named <CODE>mapcar</CODE>.)
+
+<P>How, then, do you tell Common Lisp that you want to use the procedure named
+<CODE>sqrt</CODE> as data?  You must use the <CODE>function</CODE> special
+form.<A NAME="text1" HREF="appendix-cl.html#ft1">[1]</A>
+
+<P><PRE>common-lisp&gt; (function sqrt)
+#&lt;PROCEDURE>
+
+common-lisp&gt; (mapcar (function sqrt) '(9 16 25 36))
+(3 4 5 6)
+</PRE>
+
+<P><CODE>Function</CODE>'s job is to look up names on the procedure
+blackboard.  (<CODE>Function</CODE> actually has a more general definition, as
+you'll see in a few paragraphs.)
+
+<P><H2><CODE><B>Lambda</B></CODE></H2>
+
+<P>In Common Lisp, as in Scheme, procedures can be named or unnamed.  Just as
+procedure names in Common Lisp are meaningful only in certain contexts, so
+are <CODE>lambda</CODE> expressions.  They make sense at the beginning of an
+expression:
+
+<P><PRE>common-lisp&gt; ((lambda (x) (* x x)) 4)
+16
+</PRE>
+
+<P>or as the argument to <CODE>function</CODE>:
+
+<P><PRE>common-lisp&gt; (function (lambda (x) (* x x)))
+#&lt;PROCEDURE>
+
+common-lisp&gt; (mapcar (function (lambda (x) (* x x))) '(3 4 5 6))
+(9 16 25 36)
+</PRE>
+
+<P>but they're meaningless on their own:
+
+<P><PRE>common-lisp&gt; (lambda (x) (* x x))
+ERROR: LAMBDA is not a function
+
+common-lisp&gt; (mapcar (lambda (x) (* x x)) '(3 4 5 6))
+ERROR: LAMBDA is not a function
+</PRE>
+
+<P><H2>More about <CODE><B>Function</B></CODE></H2>
+
+<P>The official rule is that <CODE>function</CODE> returns the &quot;functional
+interpretation&quot; of its argument.  If the argument is a symbol, that means
+looking up the procedure associated with that name.  If the argument is a
+<CODE>lambda</CODE> expression, it means creating a new procedure.  <CODE>Function</CODE>
+uses the same rule that's used to interpret the first element of a procedure
+invocation.
+
+<P>Since <CODE>function</CODE> is a very commonly used special form, it has an
+abbreviation:
+
+<P><PRE>common-lisp&gt; (mapcar #'(lambda (x) (* x x)) '(3 4 5 6))
+(9 16 25 36)
+
+common-lisp&gt; (mapcar #'cdr '((hey jude) (eleanor rigby) (yes it is)))
+((JUDE) (RIGBY) (IT IS))
+</PRE>
+
+<P>Don't confuse
+
+<P><PRE>#'(lambda (x) (* x x))
+</PRE>
+
+<P>with
+
+<P><PRE>'#(lambda (x) (* x x))
+</PRE>
+
+<P>The first of these is a function that squares its argument; the
+second is an array containing three elements.
+
+<P>It's unfortunate that the abbreviation for <CODE>function</CODE> contains a single
+quote mark, because the job of <CODE>function</CODE> is nothing like the job of
+<CODE>quote</CODE>.  You'll just have to get used to the &quot;hashquote&quot; notation.
+
+<P><H2>Writing Higher-Order Procedures</H2>
+
+<P>Think about this attempted translation of the <CODE>map</CODE> procedure:
+
+<P><PRE>(defun map (fn lst)                          ;; wrong!
+  (if (null lst)
+      '()
+      (cons (fn (car lst))
+	    (map fn (cdr lst)))))
+</PRE>
+
+<P>(In Common Lisp, <CODE>null</CODE> is one of the predicates whose names
+don't end in &quot;p.&quot; Otherwise, this is the same program we showed you in
+Chapter 19, except for the <CODE>defun</CODE>, of course.)
+
+<P>According to our rule about names in the front of a list, this procedure
+doesn't work.  Think about what happens when we say
+
+<P><PRE>(map #'square '(1 2 3 4 5))
+</PRE>
+
+<P>According to the substitution model, the parameters <CODE>fn</CODE> and
+<CODE>lst</CODE> are replaced in the body with <CODE>#'square</CODE> and <CODE>'(1 2 3 4 5)</CODE>.  But Common Lisp makes an exception for the first
+element of a compound expression.  It uses the procedure blackboard instead
+of substitution:
+
+<P><PRE>(if (null '(1 2 3 4 5))
+    '()
+    (cons (fn (car '(1 2 3 4 5))
+	  (map #'square (cdr '(1 2 3 4 5))))))
+</PRE>
+
+<P>Note that one of the appearances of <CODE>fn</CODE> was left unchanged.
+Since there is no global procedure named <CODE>fn</CODE>, this program will produce
+an error:
+
+<P><PRE>common-lisp&gt; (map #'square '(1 2 3 4 5))
+ERROR: FN is not a procedure.
+</PRE>
+
+<P>How, then, do you write higher-order procedures in Common Lisp?  The answer is
+that you must use <CODE>funcall</CODE>:
+
+<P><PRE>(defun map (fn lst)
+  (if (null lst)
+      '()
+      (cons (funcall fn (car lst))
+	    (map fn (cdr lst)))))
+</PRE>
+
+<P><CODE>Funcall</CODE> takes one or more arguments.  The first is a
+procedure and the rest are arguments for that procedure.  It applies that
+procedure to the given arguments.<A NAME="text2" HREF="appendix-cl.html#ft2">[2]</A> Since <CODE>fn</CODE> is no longer
+at the beginning of a compound expression, the corresponding argument,
+<CODE>#'square</CODE>, is substituted for it.
+
+<P>
+<HR>
+<A NAME="ft1" HREF="appendix-cl.html#text1">[1]</A> Common Lisp uses the word &quot;function&quot; to mean &quot;procedure,&quot;
+whether or not the procedure implements a function.<P>
+<A NAME="ft2" HREF="appendix-cl.html#text2">[2]</A> This is a lot like <CODE>apply</CODE>,
+you may have noticed.  Look at the difference:
+
+<P><PRE>common-lisp&gt; (funcall #'+ 1 2 3)
+6
+
+common-lisp&gt; (apply #'+ '(1 2 3))
+6
+</PRE>
+
+<P>In the first case, each argument to <CODE>+</CODE> is a separate argument to <CODE>funcall</CODE>.  In the second case, a list of the arguments to <CODE>+</CODE> is a
+single argument to <CODE>apply</CODE>.  <CODE>Apply</CODE> always takes exactly two
+arguments, the procedure and the argument list.<P>
+<P><A HREF="../ss-toc2.html">(back to Table of Contents)</A><P>
+<A HREF="appendix-running.html"><STRONG>BACK</STRONG></A>
+chapter thread <A HREF="appendix-simply.html"><STRONG>NEXT</STRONG></A>
+
+<P>
+<ADDRESS>
+<A HREF="../index.html">Brian Harvey</A>, 
+<CODE>bh@cs.berkeley.edu</CODE>
+</ADDRESS>
+</BODY>
+</HTML>