我想创建一个允许:
(incf vara varb varc vard)
代替
(incf vara)
(incf varb)
(incf varc)
(incf vard)
我不明白的是如何能够发送更多参数,如何在函数中定义它?
(defun inc (&rest arg) (交互式) (mapcar 'incf arg) )
这增加了参数,但当然不会将它们保存回变量中。
如何解决这个问题?
如果您希望能够在(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)
错误。
它应该工作:
(require 'cl)
(setq a 1)
(setq b 2)
(defun inc (&rest arg)
(interactive)
(mapc (lambda (x) (incf (symbol-value x))) arg))
(inc 'a 'b)
(message "%s %s" a b) => (2 3)
您必须在执行之前引用每个参数,否则(inc a b)
会变成。(inc 1 2)
inc