类似于Python的元组解包,但在Common Lisp中

13 投票
3 回答
1982 浏览
提问于 2025-04-16 17:42

有没有办法像在Python中把元组的值赋给变量一样,把一个列表的值赋给Common Lisp中的符号列表呢?

x, y, z = (1, 2, 3)

类似于这样

(setq '(n p) '(1 2))

在这里,np现在分别等于12。上面的想法只是我脑海中的构想,但实际上并不能这样做。我尝试使用apply,像这样:

(apply setq '('(n p) '(1 2)))

我刚接触Lisp,所以如果这个问题很明显,请不要太苛刻,帮我指个方向!谢谢。

附言:我看到过关于在Scheme中做到这一点的帖子,还有一个关于在Common Lisp中元组展开的类似帖子,但那些对我解决问题没有太大帮助,1)因为我不使用Scheme,2)因为最高票的回答只是一个单词apply

3 个回答

7

如果你有一个列表,想把里面的值分别赋给多个变量,那么可以用 DESTRUCTURING-BIND 这个方法。

不过,如果你想用 Python 的方式来处理“返回一个列表或元组,然后用一个列表或元组的变量来接收它”的情况,使用多个返回值和 MULTIPLE-VALUE-BIND 可能会更符合 Lisp 的风格。

10

听起来像是 destructuring-bind(在页面底部)可能能满足你的需求。

还有 HyperSpec 的描述,不过我觉得另一个链接展示得更好。

(destructuring-bind (x y z) (list 1 2 3) (+ x y z))
13

使用 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,因为它们更好,而且是执行某些类型赋值的唯一方法。

撰写回答