类似于Python的元组解包,但在Common Lisp中
有没有办法像在Python中把元组的值赋给变量一样,把一个列表的值赋给Common Lisp中的符号列表呢?
x, y, z = (1, 2, 3)
类似于这样
(setq '(n p) '(1 2))
在这里,n
和p
现在分别等于1
和2
。上面的想法只是我脑海中的构想,但实际上并不能这样做。我尝试使用apply,像这样:
(apply setq '('(n p) '(1 2)))
我刚接触Lisp,所以如果这个问题很明显,请不要太苛刻,帮我指个方向!谢谢。
附言:我看到过关于在Scheme中做到这一点的帖子,还有一个关于在Common Lisp中元组展开的类似帖子,但那些对我解决问题没有太大帮助,1)因为我不使用Scheme,2)因为最高票的回答只是一个单词apply
。
3 个回答
如果你有一个列表,想把里面的值分别赋给多个变量,那么可以用 DESTRUCTURING-BIND 这个方法。
不过,如果你想用 Python 的方式来处理“返回一个列表或元组,然后用一个列表或元组的变量来接收它”的情况,使用多个返回值和 MULTIPLE-VALUE-BIND 可能会更符合 Lisp 的风格。
听起来像是 destructuring-bind(在页面底部)可能能满足你的需求。
还有 HyperSpec 的描述,不过我觉得另一个链接展示得更好。
(destructuring-bind (x y z) (list 1 2 3) (+ x y z))
使用 DESTRUCTURING-BIND,它的功能远不止于简单的元组拆解。比如,它可以通过关键字来赋值,还可以处理可选参数等等。实际上,你可以用它做任何与函数参数列表相关的事情。
不过,如果你没有一个列表需要拆解,而是想一次性设置多个变量,可以使用 PSETF:
(psetf n 1 p 2)
你也可以使用 SETF,但 PSETF 更像是元组赋值的替代品:比如它可以用来交换或重新排列值。
# Python
n, p = p, n
x, y, z = z, x, y
;; Lisp (psetf n p p n) (psetf x z y x z y)
其实你也可以用一个普通的 LET 来解决这个问题。
另外,不要用 SETQ 来做任何事情。使用 SETF 或 PSETF,因为它们更好,而且是执行某些类型赋值的唯一方法。