(cl.info)Porting Common Lisp


Next: Function Index Prev: Old CL Compatibility Up: Top

Porting Common Lisp
*******************

This package is meant to be used as an extension to Emacs Lisp, not as
an Emacs implementation of true Common Lisp.  Some of the remaining
differences between Emacs Lisp and Common Lisp make it difficult to
port large Common Lisp applications to Emacs.  For one, some of the
features in this package are not fully compliant with ANSI or Steele;
Note: Common Lisp Compatibility..  But there are also quite a few
features that this package does not provide at all.  Here are some
major omissions that you will want watch out for when bringing Common
Lisp code into Emacs.

   * Case-insensitivity.  Symbols in Common Lisp are case-insensitive
     by default.  Some programs refer to a function or variable as
     `foo' in one place and `Foo' or `FOO' in another.  Emacs Lisp will
     treat these as three distinct symbols.

     Some Common Lisp code is written in all upper-case.  While Emacs
     is happy to let the program's own functions and variables use this
     convention, calls to Lisp builtins like `if' and `defun' will have
     to be changed to lower-case.

   * Lexical scoping.  In Common Lisp, function arguments and `let'
     bindings apply only to references physically within their bodies
     (or within macro expansions in their bodies).  Emacs Lisp, by
     contrast, uses "dynamic scoping" wherein a binding to a variable
     is visible even inside functions called from the body.

     Variables in Common Lisp can be made dynamically scoped by
     declaring them `special' or using `defvar'.  In Emacs Lisp it is
     as if all variables were declared `special'.

     Often you can use code that was written for lexical scoping even
     in a dynamically scoped Lisp, but not always.  Here is an example
     of a Common Lisp code fragment that would fail in Emacs Lisp:

          (defun map-odd-elements (func list)
            (loop for x in list
                  for flag = t then (not flag)
                  collect (if flag x (funcall func x))))
          
          (defun add-odd-elements (list x)
            (map-odd-elements (function (lambda (a) (+ a x))) list))

     In Common Lisp, the two functions' usages of `x' are completely
     independent.  In Emacs Lisp, the binding to `x' made by
     `add-odd-elements' will have been hidden by the binding in
     `map-odd-elements' by the time the `(+ a x)' function is called.

     (This package avoids such problems in its own mapping functions by
     using names like `cl-x' instead of `x' internally; as long as you
     don't use the `cl-' prefix for your own variables no collision can
     occur.)

     Note: Lexical Bindings, for a description of the `lexical-let'
     form which establishes a Common Lisp-style lexical binding, and
     some examples of how it differs from Emacs' regular `let'.

   * Common Lisp allows the shorthand `#'x' to stand for `(function
     x)', just as `'x' stands for `(quote x)'.  In Common Lisp, one
     traditionally uses `#'' notation when referring to the name of a
     function.  In Emacs Lisp, it works just as well to use a regular
     quote:

          (loop for x in y by #'cddr collect (mapcar #'plusp x))  ; Common Lisp
          (loop for x in y by 'cddr collect (mapcar 'plusp x))    ; Emacs Lisp

     When `#'' introduces a `lambda' form, it is best to write out
     `(function ...)' longhand in Emacs Lisp.  You can use a regular
     quote, but then the byte-compiler won't know that the `lambda'
     expression is code that can be compiled.

          (mapcar #'(lambda (x) (* x 2)) list)            ; Common Lisp
          (mapcar (function (lambda (x) (* x 2))) list)   ; Emacs Lisp

     Lucid Emacs supports `#'' notation starting with version 19.8.

   * The "backquote" feature uses a different syntax in Emacs Lisp.

          (defmacro foo (v &rest body) `(let ((,v 0)) @,body))  ; Common Lisp
          (defmacro foo (v &rest body) (` (let (((, v) 0)) (@, body)))  ; Emacs

   * Reader macros.  Common Lisp includes a second type of macro that
     works at the level of individual characters.  For example, Common
     Lisp implements the quote notation by a reader macro called `'',
     whereas Emacs Lisp's parser just treats quote as a special case.
     Some Lisp packages use reader macros to create special syntaxes
     for themselves, which the Emacs parser is incapable of reading.

     The lack of reader macros, incidentally, is the reason behind
     Emacs Lisp's unusual backquote syntax.  Since backquotes are
     implemented as a Lisp package and not built-in to the Emacs
     parser, they are forced to use a regular macro named ``' which is
     used with the standard function/macro call notation.

   * Other syntactic features.  Common Lisp provides a number of
     notations beginning with `#' that the Emacs Lisp parser won't
     understand.  For example, `#| ... |#' is an alternate comment
     notation, and `#+lucid (foo)' tells the parser to ignore the
     `(foo)' except in Lucid Common Lisp.

   * Packages.  In Common Lisp, symbols are divided into "packages".
     Symbols that are Lisp built-ins are typically stored in one
     package; symbols that are vendor extensions are put in another,
     and each application program would have a package for its own
     symbols.  Certain symbols are "exported" by a package and others
     are internal; certain packages "use" or import the exported symbols
     of other packages.  To access symbols that would not normally be
     visible due to this importing and exporting, Common Lisp provides
     a syntax like `package:symbol' or `package::symbol'.

     Emacs Lisp has a single namespace for all interned symbols, and
     then uses a naming convention of putting a prefix like `cl-' in
     front of the name.  Some Emacs packages adopt the Common Lisp-like
     convention of using `cl:' or `cl::' as the prefix.  However, the
     Emacs parser does not understand colons and just treats them as
     part of the symbol name.  Thus, while `mapcar' and `lisp:mapcar'
     may refer to the same symbol in Common Lisp, they are totally
     distinct in Emacs Lisp.  Common Lisp programs which refer to a
     symbol by the full name sometimes and the short name other times
     will not port cleanly to Emacs.

     Emacs Lisp does have a concept of "obarrays," which are
     package-like collections of symbols, but this feature is not
     strong enough to be used as a true package mechanism.

   * Keywords.  The notation `:test-not' in Common Lisp really is a
     shorthand for `keyword:test-not'; keywords are just symbols in a
     built-in `keyword' package with the special property that all its
     symbols are automatically self-evaluating.  Common Lisp programs
     often use keywords liberally to avoid having to use quotes.

     In Emacs Lisp a keyword is just a symbol whose name begins with a
     colon; since the Emacs parser does not treat them specially, they
     have to be explicitly made self-evaluating by a statement like
     `(setq :test-not ':test-not)'.  This package arranges to execute
     such a statement whenever `defun*' or some other form sees a
     keyword being used as an argument.  Common Lisp code that assumes
     that a symbol `:mumble' will be self-evaluating even though it was
     never introduced by a `defun*' will have to be fixed.

   * The `format' function is quite different between Common Lisp and
     Emacs Lisp.  It takes an additional "destination" argument before
     the format string.  A destination of `nil' means to format to a
     string as in Emacs Lisp; a destination of `t' means to write to
     the terminal (similar to `message' in Emacs).  Also, format
     control strings are utterly different; `~' is used instead of `%'
     to introduce format codes, and the set of available codes is much
     richer.  There are no notations like `\n' for string literals;
     instead, `format' is used with the "newline" format code, `~%'.
     More advanced formatting codes provide such features as paragraph
     filling, case conversion, and even loops and conditionals.

     While it would have been possible to implement most of Common Lisp
     `format' in this package (under the name `format*', of course), it
     was not deemed worthwhile.  It would have required a huge amount
     of code to implement even a decent subset of `format*', yet the
     functionality it would provide over Emacs Lisp's `format' would
     rarely be useful.

   * Vector constants use square brackets in Emacs Lisp, but `#(a b c)'
     notation in Common Lisp.  To further complicate matters, Emacs 19
     introduces its own `#(' notation for something entirely
     different--strings with properties.

   * Characters are distinct from integers in Common Lisp.  The
     notation for character constants is also different:  `#\A' instead
     of `?A'.  Also, `string=' and `string-equal' are synonyms in Emacs
     Lisp whereas the latter is case-insensitive in Common Lisp.

   * Data types.  Some Common Lisp data types do not exist in Emacs
     Lisp.  Rational numbers and complex numbers are not present, nor
     are large integers (all integers are "fixnums").  All arrays are
     one-dimensional.  There are no readtables or pathnames; streams
     are a set of existing data types rather than a new data type of
     their own.  Hash tables, random-states, structures, and packages
     (obarrays) are built from Lisp vectors or lists rather than being
     distinct types.

   * The Common Lisp Object System (CLOS) is not implemented, nor is
     the Common Lisp Condition System.

   * Common Lisp features that are completely redundant with Emacs Lisp
     features of a different name generally have not been implemented.
     For example, Common Lisp writes `defconstant' where Emacs Lisp
     uses `defconst'.  Similarly, `make-list' takes its arguments in
     different ways in the two Lisps but does exactly the same thing,
     so this package has not bothered to implement a Common Lisp-style
     `make-list'.

   * A few more notable Common Lisp features not included in this
     package:  `compiler-let', `tagbody', `prog', `ldb/dpb',
     `parse-integer', `cerror'.

   * Recursion.  While recursion works in Emacs Lisp just like it does
     in Common Lisp, various details of the Emacs Lisp system and
     compiler make recursion much less efficient than it is in most
     Lisps.  Some schools of thought prefer to use recursion in Lisp
     over other techniques; they would sum a list of numbers using
     something like

          (defun sum-list (list)
            (if list
                (+ (car list) (sum-list (cdr list)))
              0))

     where a more iteratively-minded programmer might write one of
     these forms:

          (let ((total 0)) (dolist (x my-list) (incf total x)) total)
          (loop for x in my-list sum x)

     While this would be mainly a stylistic choice in most Common Lisps,
     in Emacs Lisp you should be aware that the iterative forms are
     much faster than recursion.  Also, Lisp programmers will want to
     note that the current Emacs Lisp compiler does not optimize tail
     recursion.


automatically generated by info2www