【发布时间】:2022-08-20 06:55:41
【问题描述】:
我正在尝试执行以下操作:将一个从某些用户输入中获取值的函数与使用它的函数分开。
我最初尝试了以下代码来进行概念验证(有效):
(defun initialiser (bindings)
(cl-loop for (var) in bindings do
(set var (read-from-minibuffer \"Input value: \"))))
我已经测试过:
(let ((name))
(initialiser \'((name)))
(message \"name is %S\" name))
这个想法是将绑定传递给处理((name \"Name\") (address \"Post address\") (code \"County code\"))或类似形式的输入的函数,并在那里分配输入。
经过上面的测试,我想出了以下宏来做事情:
(defmacro initialise-and-execute (bindings initialiser &rest callback-actions)
(let ((unwrapped-bindings (map \'list (lambda (binding) (car binding)) bindings)))
`(let ,unwrapped-bindings
(,initialiser (quote ,bindings)
(lambda () ,@callback-actions)))))
但是,在“真实”场景中,分配必须在回调中发生,例如:
(defun initialiser(bindings)
(cl-loop for (var) in bindings collect
(lambda () (set var (read-from-minibuffer \"Input value: \")))
into callbacks
return callbacks))
这行不通。我用来测试的代码是:
(defvar callbacks nil)
(let ((name))
(setq callbacks (initialiser \'((name)))))
(funcall (car callbacks))
编辑:通过以下方式更改代码:
(defmacro initialise-and-execute (bindings initialiser &rest callback-actions)
(let ((unwrapped-bindings (map \'list (lambda (binding) (car binding)) bindings)))
`(lexical-let ,unwrapped-bindings
(,initialiser
(quote ,(map \'list
(lambda (binding) (list (cadr binding)
`(lambda (val) (setq ,(car binding) val))))
bindings))
(lambda () ,@callback-actions)))))
它必须做什么:生成多个共享相同词法环境的 lambda - 一个使用捕获的变量,其余的修改它们。
然而,遗憾的是,我得到的是别的东西。 callback-actions 中使用的符号不会解析为值集。
为了完整起见,这是我测试它的方法:
(defun init-values (bindings callback)
(loop for (desc setter) in bindings
for idx = 0 then (incf idx)
do (print (format \"Setting %s\" desc))
(funcall setter idx))
(funcall callback))
(initialise-and-execute
((name \"Name\")
(surname \"Surname\"))
init-values
(message \"name is %S\" name))
这里,lambdas 不是在loop 中生成的,而词法绑定上下文中的值是用setq 分配的。
-
这个比较不清楚。简单地传递符号应该可以轻松工作。您能否提供一个没有复杂宏的minimal reproducible example,只提供一些绑定但未定义的符号,并演示
(set symbol value)之类的东西如何不像您预期的那样工作?但是,我猜你真的是在叫错树。 -
添加了一个可复制的示例
-
如果您想将符号和值之间的某种关联传递给某些东西,那么传递 alist 或哈希表或类似的东西几乎总是更好。
set几乎从来都不是您想要做的。