2
1

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.

リーダーマクロとSLIME

Last updated at Posted at 2018-08-13

自分用のリーダーマクロやcl-annot等のライブラリを使う際に、SLIMEとの連携で多少つまづいたのでメモ。

リーダーマクロを含むコードをSLIMEで評価する

例えばcl-annotを使うとすると、ファイルの書き出しはこんな風になるでしょう1

;; 必要なら
(eval-when (:compile-toplevel :load-toplevel :execute)
  (ql:quickload :cl-annot))

(defpackage #:annot-test
  (:use :cl))
(in-package #:annot-test)
(annot:enable-annot-syntax)

@export
(defun add (x y)
  (+ x y))

(annot:enable-annot-syntax)以降はアノテーションが有効になりますが、SLIME上では@export (defun...の部分をC-c C-c slime-compile-defunすると

The variable @EXPORT is unbound.
   [Condition of type UNBOUND-VARIABLE]

というエラーがでます(環境にもよるかもしれません)。これはEmacs側で(require 'slime-annot)としておいても解決しません。

SLIMEと正しく連携できるようにするためにはcl-syntaxを使うと良いようです。cl-annotはcl-syntaxの中の1モジュール(cl-syntax-annot)として利用できます。

(eval-when (:compile-toplevel :load-toplevel :execute)
  (ql:quickload :cl-syntax-annot))

(defpackage #:annot-test
  (:use :cl))
(in-package #:annot-test)
(syntax:use-syntax :annot)

@export
(defun add (x y)
  (+ x y))

(annot:enable-annot-syntax)(syntax:use-syntax :annot)に置き換わっただけです。今度はC-c C-cで問題なく@export (defun...全体が評価されるようになりました。

リーダーマクロを含むコードをSLIMEで展開する

しかし、問題はまだあります。例えばannot:defannotationで新しいアノテーションを導入する時など、リーダーマクロの展開がどうなっているかSLIME上で確かめながら書きたいことがあります。通常のケースではC-c C-m slime-expand-1でマクロ展開を表示して、同時にリーダーマクロの展開も確認すれば十分なわけですが、この場合は@export...の位置でC-c C-mしても正しく展開されません2

これは実践的には、トップレベルフォームをマクロ展開するコマンドがあれば解決になっていると思われます。~/.emacs.d/init.elなどに、以下を定義しましょう(あるいはslime.elを書き換えても良い)。

(defun slime-eval-macroexpand-toplevel (expander)
  (let ((string (slime-defun-at-point)))
    (setq slime-eval-macroexpand-expression `(,expander ,string))
    (slime-eval-async slime-eval-macroexpand-expression
      #'slime-initialize-macroexpansion-buffer)))

(defun slime-expand-1-toplevel (&optional repeatedly)
  "Display the macro expansion of the current toplevel form.
See `slime-expand-1'."
  (interactive "P")
  (slime-eval-macroexpand-toplevel
   (if repeatedly
       'swank:swank-expand
     'swank:swank-expand-1)))

(defun my-slime-mode-hooks ()
  (define-key slime-mode-map "\C-\M-m" #'slime-expand-1-toplevel))
(add-hook 'slime-mode-hook 'my-slime-mode-hooks)

先ほどの@export (defun...の中でC-M-m slime-expand-1-toplevelを実行すると、別バッファに

(PROGN (EXPORT 'ADD) (DEFUN ADD (X Y) (+ X Y)))

と展開されるようになりました。リーダーマクロに絡んだケース以外でも役には立つコマンドかと思います。

  1. defpackageと分散されたエクスポート宣言の相性の問題については、ひとまず考えないことにします。

  2. cl-syntaxの導入によって(slime-defun-at-point)は正しく動作するようになりますが、(slime-sexp-at-point)は依然としてうまく動かないのが原因のようです。

2
1
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
2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?