1

次のことを可能にする関数を作成したいと思います。

(incf vara varb varc vard)

それ以外の

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

私が理解していないのは、より多くの引数を送信できるようにする方法、関数でそれを定義する方法です?

(defun inc (&rest arg) (インタラクティブ) (mapcar 'incf arg) )

これにより引数が増加しますが、もちろんそれらを変数に保存し直すことはありません。

これについてどうすればいいですか?

4

2 に答える 2

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)ます。

于 2013-01-24T12:53:23.370 に答える
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 1 2)inc

于 2013-01-24T10:31:53.157 に答える