関数の引数をlexical-letするマクロ
◎続編を書きましたのでそちらもよろしく。
Emacs Lispを書いていると関数の引数が動的スコープで困ることがある。で、書いてみたマクロ
(require 'cl) (defmacro* defun% (name args &rest rest) (let* ((docstr (when (and rest (stringp (car rest))) (car rest))) (body (if docstr (cdr rest) rest)) (pred (lambda (x) (string-prefix-p "&" (symbol-name x)))) (args- (remove-if pred args)) (args- (mapcar (lambda (a) `(,a ,a)) args-))) (append `(defun ,name ,args) (when docstr `(,docstr)) `((lexical-let ,args- ,@body)))))
たとえば
(defun% foo (x y z) (+ x y z))
と書くと
(defun foo (x y z) (lexical-let ((x x) (y y) (z z)) (+ x y z)))
という風に展開してくれる。
制限事項
- &optional はデフォルト値指定不可(elispだとそもそも無理?)
&key はサポートしてない。
追記(2012/12/11)
emacs lispのdefunは、&keyも&auxもサポートしていませんでした。&restと&optionalがサポートされていますが、&optionalはデフォルト値は指定できません。これらを使いたいときはclモジュールで定義されているマクロdefun*を使いましょう。ただしdefun*の引数もdefun同様に動的スコープみたいです。