Me estoy enseñando un poco más de elisp y he encontrado el siguiente problema:
Si quiero restablecer una variable de lista, no se actualizará después de la primera evaluación. Aquí hay un código de ejemplo:
(defun initilize ()
(setq example '(3)))
(defun modify ()
(initilize)
(message "%S" example)
(setcar example 2))
; M-x eval-buffer RET
(modify) ; message --> (3)
(modify) ; message --> (2)
(modify) ; message --> (2)
Estoy interesado en dos cosas. La primera es aprender más sobre lo que está sucediendo "bajo el capó", entonces, ¿por qué funciona la primera vez y falla en llamadas posteriores?
La segunda pregunta, más práctica, es cómo reiniciar la lista correctamente o ¿hay otra forma común de hacer algo así?
Una solución alternativa que encontré es usar una lista citada y evaluar el contenido de esta manera:
(setq example `(,3))
example
nunca se ha declarado como una variable, por lo que setq
debe actuar como si declarara una nueva variable, pero más tarde, cuando llame initialize
nuevamente, se creará una nueva variable, mientras modify
recuerda la anterior ... en cualquier caso, este no es un comportamiento esperado, sin embargo, el uso de setq
algo que no se ha introducido anteriormente como una variable también podría estar indefinido.
'(3)
se trata como un valor literal, así que una vez (setcar '(3) 2)
, cada vez que haces (defvar foo '(3))
o (let ((foo '(3)))
etc. Es probable que obtener un valor de foo
igual a '(2)
. Digo "probable" porque este comportamiento no está garantizado, es un tipo de optimización que el intérprete hace cuando se siente, algo conocido como eliminación de subexpresiones constantes (un caso particular de). Entonces, lo que escribió abo-abo no es exactamente la razón. Es más como modificar un literal de cadena en C (que generalmente genera una advertencia).
'(some list)
a estareq
a'(some list)
- nunca .Hay general hay garantía de que en Lisp código que visiblemente cita una lista de declaraciones de nueva estructura de la lista cada vez. En algunas implementaciones de Lisp podría, o podría ser, algunas veces. En otros, nunca lo hace. Su código no debería depender de ningún comportamiento de la implementación. Si quieres nueva estructura de la lista, el usolist
ocons
o equivalente.