bbatsov / emacs-lisp-style-guide

A community-driven Emacs Lisp style guide
1.08k stars 53 forks source link

Use uninterned symbols in expanded let-forms of macros #54

Open TobiasZawada opened 5 years ago

TobiasZawada commented 5 years ago

Use uninterned symbols in expanded let-forms of macros if the values of these symbols are for macro-internal use only.

;; bad:
(defmacro i-interned (&rest body)
  (declare (debug (body)))
  `(let ((i 1))
     (progn
       (message "Macro internal value of i: %s" i)
       ,@body)))

;; good:
(defmacro i-uninterned (&rest body)
  (declare (debug (body)))
  (let ((i (make-symbol "i")))
    `(let ((,i 1))
       (progn
     (message "Macro internal value of i: %s" ,i)
     ,@body))))

(let ((i 0))
  (i-interned
   (message "Value of i: %s" i)))

(let ((i 0))
  (i-uninterned
   (message "Value of i: %s" i)))

Output in the *Messages* buffer:

Macro internal value of i: 1
Value of i: 1
Macro internal value of i: 1
Value of i: 0
Fuco1 commented 5 years ago

Agreed, I've seen this in quite some projects around where things worked just by accident of naming being "compatible".

rprimus commented 5 years ago

Wed Jun 19 17:03:21 BST 2019

Question - wouldn't this be a use case for gensym?

Fuco1 commented 5 years ago

You can use gensym or make-symbol, the end result is the same except make-symbol has nicer naming when you macroexpand. gensym is actually a wrapper around make-symbol. But yea, doesn't matter much.