Setf expansión extraña

7

Intentando entender qué setfpuedo hacer, llamé

(macroexpand '(setf (aref vec i) val))
⇒ (let* ((v vec) (v i)) (aset v v val))

Esto parece obviamente incorrecto.

Sin embargo, no pude crear una instancia real donde (setf (aref ..falla. P.ej

 (setq vec (make-vector 10 nil) i 3 val 'foo)
 ⇒ foo
 (setf (aref vec i) val)
 ⇒ foo
 vec
 ⇒ [nil nil nil foo nil nil nil nil nil nil]

¿Alguien puede explicar lo que está pasando aquí?

phs
fuente
2
OKAY. Entiendo ahora. Los dos vsímbolos no son lo mismo y (let* ((form (macroexpand '(setf (aref vec i) val))) (symb1 (caar (cadr form))) (symb2 (caar (cdadr form)))) (equal symb1 symb2))regresa nil.
phs
1
Extrañamente, el código para setfen el archivo de origen gv.elparece crear los vsímbolos con un uso de la vainilla (gensym "v")y esto se debe agregar un valor de contador después del prefijo "v", la creación de símbolos uninterned v0, v1, v2, etc.
PHS
2
Es posible que desee jugar print-gensympara ver mejor lo que está sucediendo.
Stefan
@stefan: Tengo emacs-26.1 y no tiene print-gensymAFAICT :-( ¿Alguien tiene una explicación de por qué el (gensym "v")archivo fuente gv.elno se gensym-counter
adjunta
1
Estoy bastante seguro de que sí print-gensym, es probable que haya buscado en el lugar equivocado (intente en C-h olugar de C-h f). El let*en su código expandido es probablemente generado por macroexp-let2qué usos en make-symbollugar de gensym.
Stefan

Respuestas:

8

De tu comentario lo has descubierto por ti mismo, pero ...

En la expansión de macro está viendo la representación impresa de dos símbolos independientes con el mismo nombre. Lo más probable es que ambos símbolos no estén entrelazados.

Una representación impresa como esta, si se pasa de nuevo al lector de lisp, no sería equivalente al original, ya que el lector de lisp internaría los símbolos.

Esto es similar a:

(list (make-symbol "v") (make-symbol "v"))
(v v)
phils
fuente
3
A tener en cuenta que la configuración print-gensymy print-circleal tproduce una representación impresa que se puede leer de nuevo a algo equivalente.
npostavs