2013-01-24 45 views
1

我想創建一個功能,它允許:一次增加幾個變量,使用&rest?

(incf vara varb varc vard)

而不是

(incf vara) (incf varb) (incf varc) (incf vard)

我不明白的是如何能夠發送更多的參數,如何在一個函數中定義?

(defun定義INC(&休息ARG) (互動) (mapcar「INCF ARG) )

這增加了參數,但ofcourse不保存它們放回變量。

如何去做這件事?

+0

你或多或少在兩週前問過這個問題。 http://stackoverflow.com/questions/14292227/emacs-defining-a-function-that-sets-arguments-to-0/14293387 – phils

回答

2

它應該工作:

(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之前變得(inc 1 2)

+0

這是你建議做的方式,使用&休息嗎? – PascalVKooten

+0

'&rest'可以讓你不僅僅指出一些參數。其餘的就像'(defun inc(a b)..)'或'(defun inc(a b c)..)'。 – artscan

+1

我建議你使用'dolist'而不是'mapc'。它稍微更高效(字節編譯器不知道如何爲你做轉換)。 – Stefan

8

如果你希望能夠寫出這種形式(my-incf a b c)沒有引用變量名abc,使其宏而不是函數:

(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)錯誤進入調試器。