7

Trying to understand what setf can do, I called

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

This seems obviously wrong.

However I couldn't create an actual instance where (setf (aref .. fails. E.g.

 (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]

Can someone explain what is going on here?

Drew
  • 75,699
  • 9
  • 109
  • 225
phs
  • 1,095
  • 6
  • 13
  • 2
    OK. I understand now. The two `v` symbols are not the same and `(let* ((form (macroexpand '(setf (aref vec i) val))) (symb1 (caar (cadr form))) (symb2 (caar (cdadr form)))) (equal symb1 symb2))` returns `nil`. – phs Mar 11 '19 at 09:58
  • 1
    Strangely, the code for `setf` in source file `gv.el` seems to create the `v` symbols with a vanilla use of `(gensym "v")` and this should append a counter value after the "v" prefix, creating uninterned symbols `v0`, `v1`, `v2`, etc. – phs Mar 11 '19 at 10:05
  • 2
    You might like to play with `print-gensym` to better see what's going on. – Stefan Mar 11 '19 at 12:35
  • @stefan: I have emacs-26.1 and it has no `print-gensym` AFAICT :-( Does anyone have an explanation why the `(gensym "v")` in source file `gv.el` does not append `gensym-counter` ?! – phs Mar 11 '19 at 13:59
  • 1
    I'm pretty sure you do have `print-gensym`, you likely just looked at the wrong place (try `C-h o` instead of `C-h f`). The `let*` in your expanded code is likely generated by `macroexp-let2` which uses `make-symbol` rather than `gensym`. – Stefan Mar 11 '19 at 19:01
  • @stefan. Oh ... I stupidly assumed that `print-gensym` was a function's name. (It sounds like one, no?) 1.0E99 thanks for the tips, I'm always happy to learn more about emacs. And I must say I was quite dumbfounded when I first saw the weird expansion. I feel better now that I understand why it was a false alarm. – phs Mar 12 '19 at 06:03

1 Answers1

8

From your comment you've figured this out for yourself, but...

In the macro expansion you're seeing the printed representation of two independent symbols with the same name. Most likely both of those symbols are uninterned.

A printed representation like this, if passed back to the lisp reader, would not be equivalent to the original, as the lisp reader would intern the symbols.

This is similar to:

(list (make-symbol "v") (make-symbol "v"))
(v v)
phils
  • 48,657
  • 3
  • 76
  • 115
  • 3
    Worth noting that setting `print-gensym` and `print-circle` to `t` produces a printed representation which can read back to something equivalent. – npostavs Mar 11 '19 at 22:31