(cl.info)Efficiency Concerns

Next: Common Lisp Compatibility Prev: Assertions Up: Top

Efficiency Concerns


Many of the advanced features of this package, such as `defun*',
`loop', and `setf', are implemented as Lisp macros.  In byte-compiled
code, these complex notations will be expanded into equivalent Lisp
code which is simple and efficient.  For example, the forms

     (incf i n)
     (push x (car p))

are expanded at compile-time to the Lisp forms

     (setq i (+ i n))
     (setcar p (cons x (car p)))

which are the most efficient ways of doing these respective operations
in Lisp.  Thus, there is no performance penalty for using the more
readable `incf' and `push' forms in your compiled code.

   *Interpreted* code, on the other hand, must expand these macros
every time they are executed.  For this reason it is strongly
recommended that code making heavy use of macros be compiled.  (The
features labelled "Special Form" instead of "Function" in this manual
are macros.)  A loop using `incf' a hundred times will execute
considerably faster if compiled, and will also garbage-collect less
because the macro expansion will not have to be generated, used, and
thrown away a hundred times.

   You can find out how a macro expands by using the `cl-prettyexpand'

 - Function: cl-prettyexpand FORM &optional FULL
     This function takes a single Lisp form as an argument and inserts
     a nicely formatted copy of it in the current buffer (which must be
     in Lisp mode so that indentation works properly).  It also expands
     all Lisp macros which appear in the form.  The easiest way to use
     this function is to go to the `*scratch*' buffer and type, say,

          (cl-prettyexpand '(loop for x below 10 collect x))

     and type `C-x C-e' immediately after the closing parenthesis; the

          (block nil
            (let* ((x 0)
                   (G1004 nil))
              (while (< x 10)
                (setq G1004 (cons x G1004))
                (setq x (+ x 1)))
              (nreverse G1004)))

     will be inserted into the buffer.  (The `block' macro is expanded
     differently in the interpreter and compiler, so `cl-prettyexpand'
     just leaves it alone.  The temporary variable `G1004' was created
     by `gensym'.)

     If the optional argument FULL is true, then *all* macros are
     expanded, including `block', `eval-when', and compiler macros.
     Expansion is done as if FORM were a top-level form in a file being
     compiled.  For example,

          (cl-prettyexpand '(pushnew 'x list))
               -| (setq list (adjoin 'x list))
          (cl-prettyexpand '(pushnew 'x list) t)
               -| (setq list (if (memq 'x list) list (cons 'x list)))
          (cl-prettyexpand '(caddr (member* 'a list)) t)
               -| (car (cdr (cdr (memq 'a list))))

     Note that `adjoin', `caddr', and `member*' all have built-in
     compiler macros to optimize them in common cases.

Error Checking

Common Lisp compliance has in general not been sacrificed for the sake
of efficiency.  A few exceptions have been made for cases where
substantial gains were possible at the expense of marginal
incompatibility.  One example is the use of `memq' (which is treated
very efficiently by the byte-compiler) to scan for keyword arguments;
this can become confused in rare cases when keyword symbols are used as
both keywords and data values at once.  This is extremely unlikely to
occur in practical code, and the use of `memq' allows functions with
keyword arguments to be nearly as fast as functions that use
`&optional' arguments.

   The Common Lisp standard (as embodied in Steele's book) uses the
phrase "it is an error if" to indicate a situation which is not
supposed to arise in complying programs; implementations are strongly
encouraged but not required to signal an error in these situations.
This package sometimes omits such error checking in the interest of
compactness and efficiency.  For example, `do' variable specifiers are
supposed to be lists of one, two, or three forms; extra forms are
ignored by this package rather than signalling a syntax error.  The
`endp' function is simply a synonym for `null' in this package.
Functions taking keyword arguments will accept an odd number of
arguments, treating the trailing keyword as if it were followed by the
value `nil'.

   Argument lists (as processed by `defun*' and friends) *are* checked
rigorously except for the minor point just mentioned; in particular,
keyword arguments are checked for validity, and `&allow-other-keys' and
`:allow-other-keys' are fully implemented.  Keyword validity checking
is slightly time consuming (though not too bad in byte-compiled code);
you can use `&allow-other-keys' to omit this check.  Functions defined
in this package such as `find' and `member*' do check their keyword
arguments for validity.

Optimizing Compiler

The byte-compiler that comes with Emacs 18 normally fails to expand
macros that appear in top-level positions in the file (i.e., outside of
`defun's or other enclosing forms).  This would have disastrous
consequences to programs that used such top-level macros as `defun*',
`eval-when', and `defstruct'.  To work around this problem, the "CL"
package patches the Emacs 18 compiler to expand top-level macros.  This
patch will apply to your own macros, too, if they are used in a
top-level context.  The patch will not harm versions of the Emacs 18
compiler which have already had a similar patch applied, nor will it
affect the optimizing Emacs 19 byte-compiler written by Jamie Zawinski
and Hallvard Furuseth.  The patch is applied to the byte compiler's
code in Emacs' memory, *not* to the `bytecomp.elc' file stored on disk.

   The Emacs 19 compiler (for Emacs 18) is available from various Emacs
Lisp archive sites such as `archive.cis.ohio-state.edu'.  Its use is
highly recommended; many of the Common Lisp macros emit code which can
be improved by optimization.  In particular, `block's (whether explicit
or implicit in constructs like `defun*' and `loop') carry a fair
run-time penalty; the optimizing compiler removes `block's which are
not actually referenced by `return' or `return-from' inside the block.

automatically generated by info2www