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?

6
  • 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
    Commented Mar 11, 2019 at 9: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
    Commented Mar 11, 2019 at 10:05
  • 2
    You might like to play with print-gensym to better see what's going on.
    – Stefan
    Commented Mar 11, 2019 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
    Commented Mar 11, 2019 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
    Commented Mar 11, 2019 at 19:01

1 Answer 1

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)
1
  • 3
    Worth noting that setting print-gensym and print-circle to t produces a printed representation which can read back to something equivalent.
    – npostavs
    Commented Mar 11, 2019 at 22:31

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.