¿Cómo evaluar las variables antes de agregarlas a una lista?

30

Lo siguiente obviamente no funciona y de ahí esta pregunta.

¿Cómo corrijo el siguiente código para que el valor de se somelistconvierta '(("abc" . 123))?

(setq x "abc")
(setq y 123)
(setq somelist nil)
(add-to-list 'somelist '(x . y))
Kaushal Modi
fuente
55
¿Has probado la cuasiquoting? Tratar `(,x . ,y).
Dan
Ah, eso es lo que me perdí. No sabía para qué googlear :). Lo intenté (add-to-list 'somelist '(,x . ,y))pero olvidé la cita.
Kaushal Modi
Las preguntas consideradas como duplicados de este se repiten muy a menudo. ¿Alguien puede encontrar una manera de dejar más claro a los principiantes que esta pregunta / respuesta es lo que están buscando? Sospecho que parte del problema es que el título de esta pregunta solo tiene sentido si ya conoce la causa raíz del problema (es decir, sabe la respuesta). Estoy tratando de imaginarme a mí mismo como un usuario que no tiene idea de que las variables necesitan ser evaluadas y menos aún de lo que significa la "cita", pero estoy vacío. @¿Dibujó?
Stefan
@stefan: a diferencia del caso donde hay un mensaje de error (que puede usarse en el título de la pregunta de una comunidad Q + A), el error, si lo hay, resulta de citar algo que necesita ser evaluado (y este es un particular caso de eso) puede estar muy lejos del sitio de la cita. Más comúnmente, no hay ningún error (Emacs), solo un comportamiento que no corresponde a lo que el usuario quería.
Dibujó
@Stefan: No me viene a la mente un gran título de preguntas para esto. Pero al menos podríamos formular una pregunta que lo aborde directamente, incluido quizás un caso "normal" que requiera simplemente eliminar una comilla y un caso que requiera una quasiquoting. Sería útil una buena Q, que cubra tales casos, y una buena respuesta que los cubra. Pero en cuanto a la búsqueda de Q que son duplicados: sin un mensaje de error en el título de Q, es necesario leer toda la pregunta y saber cómo encontrar el duplicado para señalar.
Dibujó

Respuestas:

30

El problema general es que se necesita xy ypara ser evaluado antes de que se insertan en somelist. El problema con la lista citada (con 'sintaxis como lector) es que quotees una forma especial que no evalúa su argumento. De acuerdo con la cadena de documentación:

(quote ARG)

Devuelve el argumento, sin evaluarlo. (quote x)rendimientos x. Advertencia: quoteno construye su valor de retorno, sino que solo devuelve el valor que fue preconstruido por el lector Lisp ...

Por lo tanto, necesita una comilla inversa o usar una función que evalúe los argumentos.

El backquoting le permite evaluar elementos de una lista de backquoted selectivamente con la ,sintaxis:

(setq x "x-val" y "y-val" z "z-val" somelist nil)
'(x  y z)                            ; => (x y z)
`(x ,y z)                            ; => (x "y-val" z)
(add-to-list 'somelist `(x y ,z))    ; => ((x y "z-val"))

Alternativamente, se puede utilizar cons(como @tarsius sugiere en su respuesta) o, para un número arbitrario de elementos, list:

(add-to-list 'somelist (cons x y))   ; => (("x-val" . "y-val"))
(setq somelist nil)                  ; reset
(add-to-list 'somelist (list x y z)) ; => (("x-val" "y-val" "z-val"))

Cuál usar depende de lo que necesite hacer con los elementos.

Dan
fuente
19

No cite la celda cons, porque las expresiones citadas no se evalúan. Esa es exactamente la razón por la cual se cita: para evitar la evaluación. Pero eso no es lo que quieres, así que no lo hagas.

En su lugar, use el formulario que crea una celda de contras a partir de dos valores evaluados, sus argumentos.

(cons x y)

Por supuesto, también puedes hacer una cuasiquota, pero eso no tiene sentido aquí, y se ve peor. Solo use `y ,cuando eso mejore la legibilidad, es decir, al hacer algo más complejo que construir una celda de contras o agregar un átomo o una lista al comienzo de alguna lista existente.

Usando quasiquoting se vería así:

`(,x . ,y)

Lo que es peor porque usa una sintaxis adicional que no es necesaria en este caso y ofusca lo que consse está utilizando.

tarsius
fuente
3
Buen punto en consing. Quasiquoting me parece que se trata más del control detallado de los contenidos de la lista que de la legibilidad, pero estoy de acuerdo en que el caso de uso tiene sentido cons.
Dan
Gracias por su respuesta. Ese fue un gran momento TIL para mí. Citaba ciegamente citas antes de listas y contras.
Kaushal Modi
@ Dan, bueno sí, y no. Quasiquoting no puede hacer nada que no se podía hacer con sólo cons, listy nconc. Excepto ser más bonita. El azúcar sintáctico es útil cuando se necesita un "control detallado del contenido de la lista" (como "hacer algo más complejo que agregar un átomo o una lista al principio"). Y el beneficio adicional de usar ese azúcar sintáctico es: legibilidad. Quasiquoting no le brinda un control adicional más detallado, solo le permite hacer lo mismo con menos errores en el intento inicial. :-)
tarsius