18
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Emacs Lisp で括弧を省略できる式として利用できるシンボル

Last updated at Posted at 2016-12-08

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))
18
6
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
18
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?