質問: `(add-hook 'hook-name 'hoge)`などで変数名がクオートのみのもの(`'hoge`)とシャープのついたもの(`#'hoge`)を見かけますが、違いは何でしょうか。 またこれはEmacs Lisp特有でしょうか。
回答: まず、クオートは、(quote hoge)の略記、シャープクォートは、 (function hoge) の略記になります。 この、'hoge (quote hoge) と #'hoge (function hoge) の違いはEmacs 特有ではありません。 最初期のLISPである、LISP 1.5 から連綿と受け継がれているものです。 詳しく書くととても長くなるので、大きく2つに分けて、乱暴に箇条書きにしてしまうと、 ### Quote vs Function スコープ篇 1. 初期のLISP (1959年)で関数を引数にした場合意図しない動作となることが指摘される 2. LISP 1.5では、上記に対応するため、`function`と`funarg`を導入し、`quote`と使い分けるが、本当に実現したかったものは、Schemeのようにレキシカルスコープを持つ方式だった 3. Common Lispや最近のEmacs 24ではレキシカルスコープが利用できるようになった 等々ですが、Common Lispと最近のEmacs Lispでは、`quote`と`function`は、レキシカルスコープで書かれた場合に違いがでてきます。 具体的には、 * クロージャーを作る(quoteだと作れない) * ローカル関数等を作る ですが、Emacs Lispにはローカル関数がありませんので、前者の違いのみだと思います。 ### Quote vs Function 束縛アクセスの戦略篇 なぜEmacs Lispで`quote`や`function`が殆ど同じような動作になってしまったかというと、Emacs Lispの先祖のMACLISPがクロージャーのようなものは重視せず、処理系の速度向上を図ったためです。 当時の実用的なプログラミングスタイルでは、クロージャーが多用されることは考えられておらず、そこをきちんと処理して遅くなるよりは、別の部分の速度や効率を向上させよう、という選択です。 MACLISPを先祖に持つCommon Lispではレキシカルスコープが採用されたため、クロージャーもサポートされることになるのですが、Schemeとは違い、付け足した感じは否めません。 奇しくも、Emacs Lispも後付けで、lexical-binding が導入されることとなり、Common Lispと似たような状況になっています。 実際のコードでの動作の違い Emacsでの`quote`と`function`の違いですが、Emacs 24以降のlexical-binding宣言がある`lambda`の場合に動作が違ってきます。 ``` ;; -*- lexical-binding: t -*- (fset 'ffun (let ((x 0)) #'(lambda () (setq x (1+ x)) x))) (fset 'qfun (let ((x 0)) '(lambda () (setq x (1+ x)) x))) ``` をファイルに書いて、M-x load-file し、 `(qfun)`と`(ffun)`を実行してみると、qfunの方ではクロージャーが作れないことが分かります。 これは、quoteの方は単なるリストだからで、functionでなければクロージャーを作ることはできません。 コーディングスタイル Common Lispでは、関数は、`#'foo` と書くことが多いと思いますが、`'foo` でも間違いではありません。 `#'foo`と記述した方が効率良くコンパイルできたり、エラーが発見しやすくなることはあると思います。 `lambda`に関しては、Emacs Lisp、Common Lispともに`(lambda (x) x)`と書くと、`#'(lambda (x) x)`に展開されるマクロになっています。 Common Lispでは`lambda`には`#'`は付けないことが多いようです。また、Emacs Lispと違って`#'`の代わりに`'`を使うことはできません。 参考 * function の役割り * The Influence of the Designer on the Design — J.McCarthy and LISP * クロージャ再考