2011-05-16 15 views
12

¿Hay alguna forma de asignar los valores de una lista a una lista de símbolos en Common Lisp similar a la manera en que puede asignar los valores de tuple a variables en Python?Desempaquetado Tuple Similar a Python, pero en Common Lisp

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

Algo así como

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

Dónde n y p son ahora igual a 1 y 2, respectivamente. Lo anterior era solo como lo estaba pensando en mi cabeza, pero no funciona. Intenté usar aplica de la siguiente manera:

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

Soy nuevo en Lisp, así que si esto es algo que es claramente evidente, trate de no ser demasiado duro y por favor me punto en la dirección correcta! Gracias.

PD: He visto la publicación sobre cómo hacer esto en Scheme y una similar sobre la expansión de tuplas en Common Lisp, pero esas no fueron muy útiles al responder mi pregunta 1) porque no estoy usando Scheme, y 2) porque la respuesta mejor clasificada fue solo la palabra apply.

Respuesta

12

Uso DESTRUCTURING-BIND, lo que puede hacer toda una diablos de un montón más de desembalaje tupla. Como la asignación por palabras clave y parámetros opcionales, etc. En realidad, cualquier cosa que pueda hacer con la lista de parámetros de una función.

Pero si en realidad no tiene una lista para desestructurar, y desea establecer un grupo de variables a la vez, utilizar PSETF:

 
(psetf n 1 
     p 2) 

También puede utilizar SETF, pero PSETF es un análogo más cerca de la asignación de tuplas: funciona para intercambiar/permutar valores, por ejemplo.

# Python 
n, p = p, n 
x, y, z = z, x, y 
 
;; Lisp 
(psetf n p 
     p n) 
(psetf x z 
     y x 
     z y) 

realidad que probablemente podría salirse con un LET mundanas.

Además, no se moleste con SETQ por nada. Use SETF/PSETF porque son mejores y, además, la única forma de realizar ciertos tipos de asignaciones.

+2

Para intercambiar y girar, hay 'rotatef':' (rotatef n p) ',' (rotatef x y z) '. – Svante

9

Suena como destructuring-bind (su camino en la parte inferior) puede hacer lo que quiera.

También, la descripción HyperSpec, pero creo que el otro enlace lo demuestra mejor.

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

Para el caso en que tenga una lista y quiera asignar sus valores a múltiples variables, DESTRUCTURING-BIND es el camino a seguir.

Sin embargo, para la pitonica "devolver una lista o tupla, use una lista o tupla de variables para asignar a" case, es (probablemente) lispier usar valores de retorno múltiples y MULTIPLE-VALUE-BIND.