cl: Porting Common Lisp

 
 Appendix C 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; See
 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 to 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 entirely in 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).  Traditionally, Emacs
      Lisp uses “dynamic scoping” wherein a binding to a variable is
      visible even inside functions called from the body.  See
      (elisp)Dynamic Binding.  Lexical binding is available since Emacs
      24.1, so be sure to set ‘lexical-binding’ to ‘t’ if you need to
      emulate this aspect of Common Lisp.  See(elisp)Lexical
      Binding.
 
      Here is an example of a Common Lisp code fragment that would fail
      in Emacs Lisp if ‘lexical-binding’ were set to ‘nil’:
 
           (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 (lambda (a) (+ a x)) list))
 
      With lexical binding, the two functions’ usages of ‘x’ are
      completely independent.  With dynamic binding, 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.
 
      Internally, this package uses lexical binding so that such problems
      do not occur.  SeeObsolete Lexical Binding, for a description
      of the obsolete ‘lexical-let’ form that emulates a Common
      Lisp-style lexical binding when dynamic binding is in use.
 
    • 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.
 
    • 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 that 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.
 
    • 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 ‘cl-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 has
      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’ in Common Lisp
      where Emacs Lisp uses ‘?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.  However, the EIEIO package (See
      Introduction (eieio)Top.) does implement some CLOS functionality.
 
    • 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’, ‘prog’, ‘ldb/dpb’, ‘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.