バッククオートの不幸は、いつもマクロと一緒に語られることである。 だから、「バッククオートはマクロで使うものだ」と変な先入観を持たされてしまう。 また、バッククオートのもう一つの不幸は、 Emacs 19 のころの書式が複雑だったことである。 以下の例を見て欲しい。
(defmacro my-buffer-writable (& rest body) (` (let ((buffer-read-only nil) (inhibit-read-only t) (after-change-functions nil)) (,@ body)))) (macroexpand '(my-buffer-writable (insert "This is\n") (insert "a pen.\n"))) → (let ((buffer-read-only nil) (inhibit-read-only t) (after-change-functions nil)) (insert "This is\n") (insert "a pen.\n"))
この例は簡単な方だが、それでも当惑するには十分だろう。
バッククオートを理解するには、まずマクロから切り放す必要がある。 また、昔の複雑は書式は忘れよう。 そうすれば、おそらく次の言葉だけでバッククオートを理解できるはずだ。
「バッククオートとは、クオートの一種」である。 以下の例を見て欲しい。
(defvar my-lpr-call-format `("lpr" "-P" "psprinter"))
通常、クオートで書くところをバッククオートで書いてみた。 この例では、クオートとバッククオートには何ら違いはない。 だから、この例でバッククオートを使う必然性はない。 わざわざこう書いた理由は、 バッククオートとはクオート文字が逆を向いただけだと気軽に思ってもらうためだ。
では、クオートとバッククオートとの違いはなんだろう? それは、クオートはクオートした部分がまったく評価されないことに対し、 バッククオートでは一部を評価できることである。 評価したい部分の前には、"," を付ける。 以下の例をみて欲しい。
'(1 (+ 2 3) 4) → (1 (+ 2 3) 4) `(1 ,(+ 2 3) 4) → (1 5 4)
バッククオートの方では、(+ 2 3) が評価されていることが分るだろう。 この機能を利用して、前出の例は以下のようにソフトコーディングに変更できる。
(defvar my-lpr-command "lpr") (defvar my-lpr-call-format `(,my-lpr-command "-P" "psprinter"))
バッククオートには、"," に加えて、",@" という評価方法もある。 これは、評価した部分がリストになったら、 そのリストの最初と最後の括弧を取り去って、 前後とくっつける動作をする。 ",@" を使えば、先の例はさらにソフトコーディングにできる。
(defvar my-lpr-command "lpr") (defvar my-lpr-command-args '("-P" "psprinter")) (defvar my-lpr-call-format `(,my-lpr-command ,@my-lpr-command-args))
上記のようにバッククオートは、単独で使っても便利だ。 というわけで、バッククオートとマクロと一緒に語るのは、 バッククオートにとって不幸である。