このパッケージは、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 コンパイラは末尾再帰を最適化しないことを注記したいだろう。