Common lisp 在Common Lisp中将变量列表计算为其值列表
我想知道怎样才能做到以下几点。假设我有一个变量列表,这些变量由上面的Common lisp 在Common Lisp中将变量列表计算为其值列表,common-lisp,Common Lisp,我想知道怎样才能做到以下几点。假设我有一个变量列表,这些变量由上面的let绑定。我想把这个列表转换成一个值列表,这些变量被绑定到这些值上 也就是说,假设我们有 (define make-plist-from-variables (variables) (let ((keys variables) (values (mapcar #'identity variables))) (if (eq (length keys) (length values)) (ma
let
绑定。我想把这个列表转换成一个值列表,这些变量被绑定到这些值上
也就是说,假设我们有
(define make-plist-from-variables (variables)
(let ((keys variables)
(values (mapcar #'identity variables)))
(if (eq (length keys) (length values))
(make-plist keys values)
nil))))
我可以用什么来代替#“identity
来正确解压这些值
此时,下面的调用生成以下输出
CL-USER> (let ((a 2) (b 3)) (make-plist-from-variables '(a b)))
(A A B B)
我希望它是
(a2b3)
函数不能访问其调用者的词法环境。
更准确地说,在求值过程中,您不能只知道词法变量的符号就访问它们的值。只有宏才能访问
特殊变量
您可以使用动态绑定:
(defun foo ()
(declare (special a))
(symbol-value 'a))
(let ((a 3))
(declare (special a))
(foo))
=> 3
在您的情况下,您可以通过在所有符号上使用来收集符号及其值
与您的问题相关的是,如何将变量动态绑定到在计算时已知变量名称和/或值的值;请看特别接线员
宏
您可以通过编写以下代码获得关联列表:
(acons 'a a (acons 'b b nil))
根据问题背后的用例,您可能希望有一个宏扩展成这样的代码,引用您要计算的变量。它需要是一个宏,因为无法根据变量的符号获取变量的词法值
(defmacro make-plist-from-variables (&rest variables)
(loop :for binding :in variables
:collect `',binding :into result
:collect binding :into result
:finally (return `(list ,@result))))
(macroexpand-1 '(make-plist-from-variables a b))
; ==> (list 'a a 'b b)
(let ((a 2) (b 3))
(make-plist-from-variables a b))
; ==> (a 2 b 3)
编辑
不使用循环的实现
使用:
很好的代码,但是你应该解释为什么它必须是一个宏(这也在另一个答案中,但是你的答案本身应该是可以理解的)。@Barmar谢谢。刚刚做了:)看起来不错。是否可以不使用
循环
?@madpysicator在宏中,您只有表示代码的数据。不是价值观。该函数仅操作符号,并将其引用以获取符号,而不获取结果中的值。在宏中,a
和b
没有值,因为这发生在代码运行之前,可能是在编译文件时。如果你给它传递了一个错误的变量,它将毫无错误地展开,但是在运行时以后对结果的计算将失败。@MadPhysicator因此,由于我们在宏中,所以我们只有列表和符号。因此,变量名就是我们所拥有的全部。我们生成新的代码进行求值,因此`(',v,v)
生成一个引用版本和一个裸版本,例如('b)
,这样当在最终扩展中求值时,您可以得到名称,然后得到值。词汇变量在CL中没有可访问的表示。您不应该将数字与EQ进行比较。使用EQL或=。很好。谢谢
(defmacro make-plist-from-variables (&rest variables)
`(list ,@(mapcan (lambda (v) `(',v ,v)) variables))