Emacs Adevent Calendar 2016 の 12/9 が空だったため、Emacs Lisp の豆知識を入れます。
Emacs Lispでは、引数を評価しない特殊形式 quote
は頻出するため、 '
で代用できます。
すなわち以下の2式は等価で、上側の式は括弧が不要になっています。
'a
(quote a)
このように、括弧を省略できる式として扱えるシンボルが、Emacs Lisp では他に4つ用意されています。
バッククォート(すでに backquoteマクロとして定義済です)
`a
(\` a)
カンマ (バッククォート内で、特殊シンボルとして利用されています)
,a
(\, a)
カンマ・アット(バッククォート内で、特殊シンボルとして利用されています)
,@a
(\,@ a)
カンマ・ドット
,.a
(\,. a)
上記のうち、バッククォート以外は、関数やマクロとして定義されていないため、自分で利用できます。カンマ・ドットは1995年頃、 Common Lisp のバッククォートの「破壊的なスプライシング」と互換性を持たせるために Reader に導入されました。しかし、破壊的なスプライシングそのものが使いにくという理由のため、 backquote.el 本体には実装されず、かといって、Reader からもカンマ・ドットは削除されず、放置状態が続いています。
以下に、これらのシンボルを局所的な関数として利用する例を示します。
(defun example (info)
(concat
"name=" (assoc-default :name info) "\n"
"address=" (assoc-default :address info) "\n"
"tel=" (assoc-default :tel info) "\n"
...))
上記のように引数が1つだけ異なる関数を大量に呼び出す場合、それを cl-flet で以下のように置き換えると
(defun example (info)
(cl-flet ((\, (key) (assoc-default key info))))
(concat
"name=" ,:name "\n"
"address=" ,:address "\n"
"tel=" ,:tel "\n"
...)))
このようにコードをすっきりさせることができます。
コードを変数化し、別に分離する際には、 eval 時に backquote を必要とする場面がしばしばあるため、 backquote マクロに影響されないカンマ・ドットは特に有用です。
(defvar info
'((:name . "hoge") (:address . "page") (:tel . "num")))
;; ここで format を変数として分離したい。
(defvar format
'("name=" ,.:name "\n"
"address=" ,.:address "\n"
"tel=" ,.:tel "\n"))
;; 実際の評価
(defun example (info)
"Test INFO."
(eval `(cl-flet ((\,. (key) (assoc-default key info)))
,(cons 'concat format)) t))