From: Mark Kantrowitz
Subject: FAQ: Lisp Frequently Asked Questions 3/3 [Monthly posting]
Date: 
Message-ID: <lisp-faq-3.text_701168441@cs.cmu.edu>
Archive-name: lisp-faq/part3
Last-Modified: Tue Feb 25 17:34:30 1992 by Mark Kantrowitz
Version: 1.13

;;; ****************************************************************
;;; Answers to Frequently Asked Questions about Lisp ***************
;;; ****************************************************************
;;; Written by Mark Kantrowitz and Barry Margolin
;;; lisp-faq-3.text -- 16886 bytes

This post contains Part 3 of the Lisp FAQ.

If you think of questions that are appropriate for this FAQ, or would
like to improve an answer, please send email to us at ········@think.com.

Common Pitfalls (Part 3):

  [3-0]  Why does (READ-FROM-STRING "foobar" :START 3) return FOOBAR
         instead of BAR?  
  [3-1]  Why can't it deduce from (READ-FROM-STRING "foobar" :START 3)
         that the intent is to specify the START keyword parameter
         rather than the EOF-ERROR-P and EOF-VALUE optional parameters?   
  [3-2]  Why can't I apply #'AND and #'OR?
  [3-3]  I used a destructive function (e.g. DELETE, SORT), but it
         didn't seem to work.  Why? 
  [3-4]  After I NREVERSE a list, it's only one element long.  After I
         SORT a list, it's missing things.  What happened? 
  [3-5]  Why does (READ-LINE) return "" immediately instead of waiting
         for me to type a line?  
  [3-6]  I typed a form to the read-eval-print loop, but nothing happened. Why?
  [3-7]  DEFMACRO doesn't seem to work.
         When I compile my file, LISP warns me that my macros are undefined
         functions, or complains "Attempt to call <function> which is 
         defined as a macro.
  [3-8]  Name conflict errors are driving me crazy! (EXPORT, packages)
  [3-9]  Closures don't seem to work properly when referring to the
         iteration variable in DOLIST, DOTIMES and DO.
  [3-10] What is the difference between FUNCALL and APPLY?

Search for [#] to get to question number # quickly.

----------------------------------------------------------------
[3-0] Why does (READ-FROM-STRING "foobar" :START 3) return FOOBAR instead 
      of BAR?

READ-FROM-STRING is one of the rare functions that takes both &OPTIONAL and
&KEY arguments:

       READ-FROM-STRING string &OPTIONAL eof-error-p eof-value 
                               &KEY :start :end :preserve-whitespace

When a function takes both types of arguments, all the optional
arguments must be specified explicitly before any of the keyword
arguments may be specified.  In the example above, :START becomes the
value of the optional EOF-ERROR-P parameter and 3 is the value of the
optional EOF-VALUE parameter.
     
----------------------------------------------------------------
[3-1] Why can't it deduce from (READ-FROM-STRING "foobar" :START 3) that
      the intent is to specify the START keyword parameter rather than
      the EOF-ERROR-P and EOF-VALUE optional parameters?

In Common Lisp, keyword symbols are first-class data objects.  Therefore,
they are perfectly valid values for optional parameters to functions.
There are only four functions in Common Lisp that have both optional and
keyword parameters (they are PARSE-NAMESTRING, READ-FROM-STRING,
WRITE-LINE, and WRITE-STRING), so it's probably not worth adding a
nonorthogonal kludge to the language just to make these functions slightly
less confusing; unfortunately, it's also not worth an incompatible change
to the language to redefine those functions to use only keyword arguments.
     
----------------------------------------------------------------
[3-2] Why can't I apply #'AND and #'OR?

Here's the simple, but not necessarily satisfying, answer: AND and OR are
macros, not functions; APPLY and FUNCALL can only be used to invoke
functions, not macros and special operators.

OK, so what's the *real* reason?  The reason that AND and OR are macros
rather than functions is because they implement control structure in
addition to computing a boolean value.  They evaluate their subforms
sequentially from left/top to right/bottom, and stop evaluating subforms as
soon as the result can be determined (in the case of AND, as soon as a
subform returns NIL; in the case of OR, as soon as one returns non-NIL);
this is referred to as "short circuiting" in computer language parlance.
APPLY and FUNCALL, however, are ordinary functions; therefore, their
arguments are evaluated automatically, before they are called.  Thus, were
APPLY able to be used with #'AND, the short-circuiting would be defeated.

Perhaps you don't really care about the short-circuiting, and simply want
the functional, boolean interpretation.  While this may be a reasonable
interpretation of trying to apply AND or OR, it doesn't generalize to other
macros well, so there's no obvious way to have the Lisp system "do the
right thing" when trying to apply macros.  The only function associated
with a macro is its expander function; this function accepts and returns
and form, so it cannot be used to compute the value.

The Common Lisp functions EVERY and SOME can be used to get the
functionality you intend when trying to apply #'AND and #'OR.  For
instance, the erroneous form:

   (apply #'and *list*)

can be translated to the correct form:

   (every #'identity *list*)

----------------------------------------------------------------
[3-3] I used a destructive function (e.g. DELETE, SORT), but it didn't seem to
      work.  Why?

I assume you mean that it didn't seem to modify the original list.  There
are several possible reasons for this.  First, many destructive functions
are not *required* to modify their input argument, merely *allowed* to; in
some cases, the implementation may determine that it is more efficient to
construct a new result than to modify the original (this may happen in Lisp
systems that use "CDR coding", where RPLACD may have to turn a CDR-NEXT or
CDR-NIL cell into a CDR-NORMAL cell), or the implementor may simply not
have gotten around to implementing the destructive version in a truly
destructive manner.  Another possibility is that the nature of the change
that was made involves removing elements from the front of a list; in this
case, the function can simply return the appropriate tail of the list,
without actually modifying the list. And example of this is:
     
   (setq *a* (list 3 2 1))
   (delete 3 *a*) => (2 1)
   *a* => (3 2 1)

Similarly, when one sorts a list, SORT may destructively rearrange the
pointers (cons cells) that make up the list. SORT then returns the cons
cell that now heads the list; the original cons cell could be anywhere in
the list. The value of any variable that contained the original head of the
list hasn't changed, but the contents of that cons cell have changed
because SORT is a destructive function:

   (setq *a* (list 2 1 3))
   (sort *a* #'<) => (1 2 3)
   *a* => (2 3)     

In both cases, the remedy is the same: store the result of the
function back into the place whence the original value came, e.g.

   (setq *a* (delete 3 *a*))
   *a* => (2 1)

Why don't the destructive functions do this automatically?  Recall that
they are just ordinary functions, and all Lisp functions are called by
value.  Therefore, these functions do not know where the lists they are
given came from; they are simply passed the cons cell that represents the
head of the list. Their only obligation is to return the new cons cell that
represents the head of the list.

One thing to be careful about when doing this is that the original list
might be referenced from multiple places, and all of these places may need
to be updated.  For instance:

   (setq *a* (list 3 2 1))
   (setq *b* *a*)
   (setq *a* (delete 3 *a*))
   *a* => (2 1)
   *b* => (3 2 1) ; *B* doesn't "see" the change
   (setq *a* (delete 1 *a*))
   *a* => (2)
   *b* => (3 2) ; *B* sees the change this time, though

One may argue that destructive functions could do what you expect by
rearranging the CARs of the list, shifting things up if the first element
is being deleted, as they are likely to do if the argument is a vector
rather than a list.  In many cases they could do this, although it would
clearly be slower.  However, there is one case where this is not possible:
when the argument or value is NIL, and the value or argument, respectively,
is not.  It's not possible to transform the object referenced from the
original cell from one data type to another, so the result must be stored
back.  Here are some examples:

   (setq *a* (list 3 2 1))
   (delete-if #'numberp *a) => NIL
   *a* => (3 2 1)
   (setq *a* nil *b* '(1 2 3))
   (nconc *a* *b*) => (1 2 3)
   *a* => NIL

The names of most destructure functions (except for sort, delete,
rplaca, rplacd, and setf of accessor functions) have the prefix N.

In summary, the two common problems to watch out for when using
destructive functions are:

   1. Forgetting to store the result back. Even though the list
      is modified in place, it is still necessary to store the
      result back into the original location, e.g.,
           (setq foo (delete 'x foo))

      If the original list was stored in multiple places, you may
      need to store it back in all of them, e.g.
           (setq bar foo)
           ...
           (setq foo (delete 'x foo))
           (setq bar foo)

   2. Sharing structure that gets modified. If it is important
      to preserve the shared structure, then you should either
      use a nondestructive operation or copy the structure first
      using COPY-LIST or COPY-TREE.
           (setq bar (cdr foo))
           ...
           (setq foo (sort foo #'<))
           ;;; now it's not safe to use BAR

Note that even nondestructive functions, such as REMOVE, and UNION,
can return a result which shares structure with an argument. 
Nondestructive functions don't necessarily copy their arguments; they
just don't modify them.
     
----------------------------------------------------------------
[3-4] After I NREVERSE a list, it's only one element long.  After I SORT
      a list, it's missing things.  What happened?

These are particular cases of the previous question.  Many NREVERSE and
SORT implementations operate by rechaining all the CDR links in the list's
backbone, rather than by replacing the CARs.  In the case of NREVERSE, this
means that the cons cell that was originally first in the list becomes the
last one.  As in the last question, the solution is to store the result
back into the original location.
     
----------------------------------------------------------------
[3-5] Why does (READ-LINE) return "" immediately instead of waiting for
      me to type a line?

Many Lisp implementations on line-buffered systems do not discard the
newline that the user must type after the last right parenthesis in order
for the line to be transmitted from the OS to Lisp.  Lisp's READ function
returns immediately after seeing the matching ")" in the stream.  When
READLINE is called, it sees the next character in the stream, which is a
newline, so it returns an empty line.  If you were to type "(read-line)This
is a test" the result would be "This is a test".

The simplest solution is to use (PROGN (CLEAR-INPUT) (READ-LINE)).  This
discards the buffered newline before reading the input.  However, it would
also discard any other buffered input, as in the "This is a test" example
above; some implementation also flush the OS's input buffers, so typeahead
might be thrown away.

----------------------------------------------------------------
[3-6] I typed a form to the read-eval-print loop, but nothing happened. Why?

There's not much to go on here, but a common reason is that you haven't
actually typed a complete form.  You may have typed a doublequote, vertical
bar, "#|" comment beginning, or left parenthesis that you never matched
with another doublequote, vertical bar, "|#", or right parenthesis,
respectively.  Try typing a few right parentheses followed by Return.

----------------------------------------------------------------
[3-7]  DEFMACRO doesn't seem to work. 
       When I compile my file, LISP warns me that my macros are undefined
       functions, or complains "Attempt to call <function> which is 
       defined as a macro.

When you evaluate a DEFMACRO form or proclaim a function INLINE, it
doesn't go back and update code that was compiled under the old
definition. When redefining a macro, be sure to recompile any
functions that use the macro. Also be sure that the macros used in a
file are defined before any forms in the same file that use them.

Certain forms, including LOAD, SET-MACRO-CHARACTER, and
REQUIRE, are not normally evaluated at compile time. Common Lisp
requires that macros defined in a file be used when compiling later
forms in the file. If a Lisp doesn't follow the standard, it may be
necessary to wrap an EVAL-WHEN form around the macro definition.

Most often the "macro was previously called as a function" problem
occurs when files were compiled/loaded in the wrong order. For
example, developers may add the definition to one file, but use it in
a file which is compiled/loaded before the definition. To work around
this problem, one can either fix the modularization of the system, or
manually recompile the files containing the forward references to macros.

Also, if your macro calls functions at macroexpand time, those functions
may need to be in an EVAL-WHEN. For example,

    (defun some-function (x)
      x)

    (defmacro some-macro (y)
      (let ((z (some-function y)))
	`(print ',z)))

If the macros are defined in a file you require, make sure your
require or load statement is in an appropriate EVAL-WHEN. Many people
avoid all this nonsense by making sure to load all their files before
compiling them, or use a system facility (or just a script file) that
loads each file before compiling the next file in the system.

----------------------------------------------------------------
[3-8]  Name conflict errors are driving me crazy! (EXPORT, packages)

If a package tries to export a symbol that's already defined, it will
report an error. You probably tried to use a function only to discover
that you'd forgotten to load its file. The failed attempt at using the
function caused its symbol to be interned. So now, when you try to
load the file, you get a conflict. Unfortunately, understanding and
correcting the code which caused the export problem doesn't make those
nasty error messages go away. That symbol is still interned where it
shouldn't be. Use unintern to remove the symbol from a package before
reloading the file. Also, when giving arguments to REQUIRE or package
functions, use strings or keywords, not symbols: (find-package "FOO"),
(find-package :foo). 

A sometimes useful technique is to rename (or delete) a package
that is "too messed up".  Then you can reload the relevant files
into a "clean" package.

----------------------------------------------------------------
[3-9]  Closures don't seem to work properly when referring to the
       iteration variable in DOLIST, DOTIMES and DO.

DOTIMES, DOLIST, and DO all use assignment instead of binding to
update the value of the iteration variables. So something like

   (dotimes (n 10)
     (push #'(lambda () (incf n))
           *counters*))

will produce 10 closures over the same value of the variable N.
----------------------------------------------------------------
[3-10] What is the difference between FUNCALL and APPLY?

FUNCALL is useful when the programmer knows the length of the argument
list, but the function to call is either computed or provided as a
parameter.  For instance, a simple implementation of MEMBER-IF (with
none of the fancy options) could be written as:

(defun member-if (predicate list)
  (do ((tail list (cdr tail)))
      ((null tail))
   (when (funcall predicate (car tail))
     (return-from member-if tail))))

The programmer is invoking a caller-supplied function with a known
argument list.

APPLY is needed when the argument list itself is supplied or computed.
Its last argument must be a list, and the elements of this list become
individual arguments to the function.  This frequently occurs when a
function takes keyword options that will be passed on to some other
function, perhaps with application-specific defaults inserted.  For
instance:

(defun open-for-output (pathname &rest open-options)
  (apply #'open pathname :direction :output open-options))

FUNCALL could actually have been defined using APPLY:

(defun funcall (function &rest arguments)
  (apply function arguments))

----------------------------------------------------------------
;;; *EOF*