このパッケージは、Emacs Lispへの拡張として使われることを意図されており、 真のCommon LispのEmacs実装としては意図されていない。Emacs LispとCommon Lispの間の残りの相違のいくつかは、大きなCommon Lispアプリケーションを Emacsへ移植することを難しくしている。一例として、このパッケージの機能 のいくつかは、ANSIまたはSteeleに完全には従っていない; see Common Lispとの互換性. しかし、このパッケージがまったく 提供しない機能もかなり多くある。ここには、Common LispコードをEmacsに 持ってくるときに警戒したくなる、いくつかの主要な省略がある。
fooとして、別の場所ではFooまたは
FOOとして参照する。Emacs Lispはそれれを3つの別のシンボルとして
扱う。
いくつかのCommon Lispコードは、完全に大文字で書かれている。一方Emacsは、
プログラム自身の関数や変数にこの規約を喜んで使わせるので、ifや
defunのようなLisp組み込みへの呼び出しは、小文字に
変えなければならなくなるだろう。
letの束縛は、
物理的にその本体内(またはその本体のマクロ展開内)での参照にだけ
適用する。Emacs Lispでは対照的に、本体から呼び出された関数の内側でさえ
変数への束縛が見える動的スコープを使う。
Common Lispの変数は、specialと宣言するかdefvarを
使うことで動的スコープにすることができる。Emacs Lispでは、すべての
変数がspecialと宣言されているようなものである。
しばしば、動的スコープLispの中でさえレキシカルスコープのために書かれた コードを使うことができるが、常にというわけではない。これは、Emacs Lisp では失敗するCommon 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))
Common Lispでは、2つの関数のxの使用法は完全に独立している。
Emacs Lispでは、add-odd-elementsによって作られたxへの
束縛は、(+ a x)関数が呼び出される間はmap-odd-elementsの
束縛で隠されるだろう。
(このパッケージは、自身のマッピング関数の中で内部的にxではなく
cl-xのような名前を使うことで、このような問題を避ける; あなた
自身の変数のためにcl-接頭辞を使わない限り、衝突は起こらない)
Common Lispスタイルのレキシカルな束縛を確立するlexical-let
フォームの記述と、Emacs正規のletとどのように
異なるかのいくつかの例は、See レキシカルな束縛.
'と呼ばれるリーダマクロによって
引用符表記法を実装するが、Emacs Lispの構文解析器は、単に引用符を特殊な
場合として扱う。いくつかのLispパッケージは、自身用の特殊文法を
作るためにリーダマクロを使うが、それをEmacs構文解析器は読めない。
ついでに言えば、リーダマクロの欠如は、Emacs Lispの普通ではない
バッククォート文法の背後にある理由である。バッククォートはLisp
パッケージとして実装されており、Emacs構文解析器に組み
込みではないので、標準の関数/マクロ呼び出し表記法と共に使われる、
`と名付けられた正規のマクロを使うように強いられる。
#で始まるかなりの数の表記法を提供する。たとえば、
‘#| ... |#’は代替の注釈表記法であり、‘#+lucid (foo)’は、
Lucid Common Lisp内を除いて(foo)を無視するように構文解析器に
言う。
package:symbolまたはpackage::symbolのような文法を
提供する。
Emacs Lispは、すべてのinternされたシンボルに1つの名前空間を持ち、
名前の先頭にcl-のような接頭辞を置くという命名規約を使う。
いくつかのEmacsパッケージは、接頭辞としてcl:やcl::を使う
Common Lispに似た規約を採用する。しかし、Emacs構文解析器はコロンを
理解せず、単にそれらをシンボル名の一部として扱う。したがって、
mapcarとlisp:mapcarはCommon Lispでは同じシンボルを
参照するかもしれないが、Emacs Lispではそれらは完全に別のものである。
あるシンボルを、時には正式な名前で参照し、別の時には短い名前で参照する
Common Lispプログラムは、Emacsにはきれいに移植できないだろう。
Emacs Lispは“obarray”の概念を持っており、それはパッケージに似た シンボルの集積だが、この機能は真のパッケージメカニズムとして使えるほど 十分に強力ではない。
format関数は、Common LispとEmacs Lispの間でまったく違っている。
フォーマット文字列の前に、追加の“宛先”引数をとる。nilの宛先は、
Emacs Lispのように文字列をフォーマットすることを意味する; tの
宛先は、(Emacsのmessageのように)ターミナルへ書くことを
意味する。また、フォーマット制御文字列は完全に異なる;
フォーマットコードを導入するために、%の代わりに~を使い、
利用できるコードの集合はずっと豊富である。文字列リテラルの\n
のような表記法はない; その代わりに、formatは“改行”
フォーマットコードである~%とともに使われる。より高度な
フォーマットコードは、パラグラフ詰め込み、大文字小文字変換、そして
ループや条件付き実行のような機能さえ提供する。
このパッケージで、Common Lispのformatの大部分を実装することは
可能だったかもしれないとしても(もちろんformat*の名のもとに)、
時間と労力をかけるだけの値打ちがないように思われた。format*
のかなりのサブセットを実装するためですら、巨大なコード量が
必要だっただろうし、さらに、Emacs Lispのformatを越えて提供する
機能はめったに有用ではないだろう。
#(a b c)記法を使う。さらに問題を複雑にすることには、Emacs 19は、
何か完全に違うこと—属性を持つ文字列のために、それ自身の#(
表記法を導入する。
?Aの代わりに#\Aである。また、string=と
string-equalはEmacs Lispでは同義語だが、Common Lispでは後者は
大文字小文字を区別しない。
defconstを
使うところで、Common Lispはdefconstantを使う。同様に、
make-listは2つのLispで異なった方法でその引数をとるが、正確に
同じことをするので、このパッケージはCommon Lispスタイルの
make-listをわざわざ実装しなかった。
compiler-let、tagbody、prog、
ldb/dpb、parse-integer、cerror。
(defun sum-list (list)
(if list
(+ (car list) (sum-list (cdr list)))
0))
そこでは、より繰り返し的に考えるプログラマは以下のフォームの1つを 書くかもしれない:
(let ((total 0)) (dolist (x my-list) (incf total x)) total) (loop for x in my-list sum x)
これは、多くのCommon Lispではおもにスタイル上の選択だろうが、 Emacs Lispでは、繰り返しフォームは再帰よりもかなり速いことを 知っておくべきである。またLispプログラマは、現在のEmacs Lisp コンパイラは末尾再帰を最適化しないことを注記したいだろう。