変数名、、および(my-incf a b c)
を引用符で囲まずにこの形式を記述できるようにしたい場合は、関数ではなくマクロにします。a
b
c
(defmacro incf+ (&rest vars)
`(progn
,@(mapcar (lambda (var) `(incf ,var)) vars)))
次を使用して、正しいコードに展開されることを確認しますmacroexpand
。
(macroexpand '(incf+ var1 var2 var3))
;; => (progn (incf var1) (incf var2) (incf var3))
Emacs Lisp の変数にはデフォルトで動的スコープがあるため、引用符で囲まれた変数名を引数として取る関数でほぼ同じことを行うことができます。しかし、マクロ バージョンには、呼び出された場所でコードに展開されるため、字句的にバインドされた変数でも機能するという利点があります。 symbol-value
動的にバインドされた変数でのみ機能します。
以下をファイルに入れてロードすることで、これをテストできます (Emacs 24 以降)。
;; -*- lexical-binding: t -*-
(defun incf+fun (&rest vars)
(mapc #'(lambda (var) (incf (symbol-value var))) vars))
(defun incf-macro-test ()
(let ((a 5) (b 7) (c 11))
(incf+ a b c)
(list a b c)))
(defun incf-function-test ()
(let ((a 5) (b 7) (c 11))
(incf+fun 'a 'b 'c)
(list a b c)))
評価(incf-macro-test)
すると が返さ(6 8 12)
れ(incf-function-test)
ますが、エラーが発生してデバッガに入り(void-variable a)
ます。