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
fooin one place andFooorFOOin 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
ifanddefunwill have to be changed to lower case.Lexical scoping. In Common Lisp, function arguments and
letbindings 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 Dynamic Binding in GNU Emacs Lisp Reference Manual. Lexical binding is available since Emacs 24.1, so be sure to setlexical-bindingtotif you need to emulate this aspect of Common Lisp. See Lexical Binding in GNU Emacs Lisp Reference Manual.Here is an example of a Common Lisp code fragment that would fail in Emacs Lisp if
lexical-bindingwere set tonil: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 (lambda (a) (+ a x)) list))With lexical binding, the two functions’ usages of
xare completely independent. With dynamic binding, the binding toxmade byadd-odd-elementswill have been hidden by the binding inmap-odd-elementsby the time the(+ a x)function is called.Internally, this package uses lexical binding so that such problems do not occur. See Obsolete Lexical Binding, for a description of the obsolete
lexical-letform 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:symbolorpackage::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 usingcl:orcl::as the prefix. However, the Emacs parser does not understand colons and just treats them as part of the symbol name. Thus, whilemapcarandlisp:mapcarmay 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
formatfunction is quite different between Common Lisp and Emacs Lisp. It takes an additional “destination” argument before the format string. A destination ofnilmeans to format to a string as in Emacs Lisp; a destination oftmeans to write to the terminal (similar tomessagein 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\nfor string literals; instead,formatis 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
formatin this package (under the namecl-format, of course), it was not deemed worthwhile. It would have required a huge amount of code to implement even a decent subset offormat, yet the functionality it would provide over Emacs Lisp’sformatwould 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:
#\Ain Common Lisp where Emacs Lisp uses?A. Also,string=andstring-equalare 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, 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 in EIEIO) 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
defconstantwhere Emacs Lisp usesdefconst. Similarly,make-listtakes 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-stylemake-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
emacs-lisp(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:
emacs-lisp(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.