在Elisp中如何动态地将值赋给动态选择的变量(以let形式)。

时间:2013-04-13 17:15:02

标签: lisp elisp

我有一个已知变量的列表和带有nil参数列表的相应函数,在body中它使用已知的非参数(或全局)变量。

例如。

(defun funA ()
  (message "%s" varA))

(defun funB ()
  (message "%s" varB))

...

(setq alist
      '((varA . funA)
        (varB . funB)
        ...
        ))

alist中的类似元素可以动态添加/删除。

我想在另一个函数中运行所有这些函数,其中已知变量的值以LET形式动态分配。

(defun call-each-fun-of-alist ()
  (dolist (e alist)
    (let (( (car e)  (read-from-minibuffer "value: ") ))
      (funcall (cdr e)))))

(是的,它会抛出错误,但我想要类似的东西,可能没有EVAL)

对于已知的alist元素(就像我能做的那样

(let ((varA (read-from-minibuffer "value: ")))
  (funcall (cdr (assoc 'varA alist))))

但alist是动态更新的,我在alist中运行所有函数 并且相应变量的值将动态出现。

请告诉我如何定义

call-each-fun-of-alist

(不一定但没有调用EVAL里面的呼叫 - 每个乐趣的alist,如果不可能没有EVAL而不是我也想知道它。)

3 个答案:

答案 0 :(得分:3)

您可以使用letf(最近的Emacs中的cl-letf)执行此操作。它绑定let之类的值,但允许'places'或'generalized variables'以及简单的变量名。

(defun call-each-fun-of-alist ()
  (cl-dolist (e alist)
    (cl-destructuring-bind (variable . function) e
      (cl-letf (((symbol-value variable)
                 (read-from-minibuffer
                  (format "value for %s: "
                          variable))))
        (funcall function)))))

请注意,除非alist中命名的变量先前已使用defvar声明为动态变量,否则将失败并显示错误。有关详细信息,请查看Elisp手册中的“通用变量”。

另一个解决方案是使用cl-progv,它将变量名和值的并行列表动态绑定:

(defun call-each-fun-of-alist ()
  (cl-dolist (e alist)
    (cl-destructuring-bind (variable . function) e
      (cl-progv
          (list variable)
          (list (read-from-minibuffer
                 (format "value for %s: "
                         variable)))
        (funcall function)))))

答案 1 :(得分:1)

在Common Lisp中,这是由PROGV提供的 - 给定变量符号的变量的动态绑定。

GNU Emacs在Common Lisp仿真中应该有PROGV

答案 2 :(得分:0)

这就是你所需要的 - 不需要progv或破坏绑定东西:

(defun call-each-fun-of-alist (alist)
  (dolist (e  alist)
    (set (car e) (read-from-minibuffer "value: "))
    (funcall (cdr e))))

(defvar my-alist '((varA . funA) (varB . funB)))
(call-each-fun-of-alist my-alist)

或者,如果你真的想因某种原因看到let绑定:

(defun call-each-fun-of-alist (alist)
  (dolist (e  alist)
    (eval `(let ((,(car e)  (read-from-minibuffer "value: ")))
             (funcall (cdr e))))))