Next: Common Lisp Compatibility, Previous: Assertions and Errors, Up: GNU Emacs Common Lisp Emulation [Contents][Index]
Many of the advanced features of this package, such as cl-defun
,
cl-loop
, etc., 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 form
(cl-incf i n)
is expanded at compile-time to the Lisp form
(setq i (+ i n))
which is the most efficient way of doing this operation
in Lisp. Thus, there is no performance penalty for using the more
readable cl-incf
form 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.
A loop using cl-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.
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 that appear in the form. The easiest way to use this function is to go to the *scratch* buffer and type, say,
(cl-prettyexpand '(cl-loop for x below 10 collect x))
and type C-x C-e immediately after the closing parenthesis; an expansion similar to:
(cl-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 cl-block
macro is
expanded differently in the interpreter and compiler, so
cl-prettyexpand
just leaves it alone. The temporary
variable G1004
was created by cl-gensym
.)
If the optional argument full is true, then all
macros are expanded, including cl-block
, cl-eval-when
,
and compiler macros. Expansion is done as if form were
a top-level form in a file being compiled.
Note that cl-adjoin
and cl-member
have built-in compiler
macros to optimize them in common cases.
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.
The Common Lisp standard (as embodied in Steele’s book) uses the
phrase “it is an error if” to indicate a situation that 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, cl-do
variable
specifiers are supposed to be lists of one, two, or three forms; extra
forms are ignored by this package rather than signaling a syntax
error. 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 cl-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 cl-find
and cl-member
do check their keyword arguments for validity.
Changing the value of byte-optimize
from the default t
is highly discouraged; many of the Common
Lisp macros emit
code that can be improved by optimization. In particular,
cl-block
s (whether explicit or implicit in constructs like
cl-defun
and cl-loop
) carry a fair run-time penalty; the
byte-compiler removes cl-block
s that are not actually
referenced by cl-return
or cl-return-from
inside the block.
Next: Common Lisp Compatibility, Previous: Assertions and Errors, Up: GNU Emacs Common Lisp Emulation [Contents][Index]