我想创建一个允许以下内容的函数:
(incf vara varb varc vard)
代替
(incf vara)
(incf varb)
(incf varc)
(incf vard)
我不明白的是如何能够发送更多的参数,如何在函数中定义它?
(defun inc(&rest arg)(互动)(mapcar'inff arg))
这增加了论证,但当然不会将它们保存回变量中.
怎么去这个?
如果你希望能够写这个形式(my-incf a b c)
没有引用变量名a
,b
和c
,使其宏而不是函数:
(defmacro incf+ (&rest vars)
`(progn
,@(mapcar (lambda (var) `(incf ,var)) vars)))
Run Code Online (Sandbox Code Playgroud)
使用以下命令检查它是否扩展为正确的代码macroexpand
:
(macroexpand '(incf+ var1 var2 var3))
;; => (progn (incf var1) (incf var2) (incf var3))
Run Code Online (Sandbox Code Playgroud)
因为默认情况下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)))
Run Code Online (Sandbox Code Playgroud)
评估(incf-macro-test)
将返回(6 8 12)
,但(incf-function-test)
将进入调试器并显示(void-variable a)
错误.