with-unique-names ({var | (var prefix)}*) declaration* form* => result*

Arguments and Values:

var---a symbol; not evaluated.

prefix---a string designator; not evaluated. The default is var.

declaration---a declare expression; not evaluated.

form---a form.

results---the values returned by the forms.


Executes a series of forms with each var bound to a fresh, uninterned symbol. The uninterned symbol is created as if by a call to gensym with the string denoted by prefix---or, if prefix is not supplied, the string denoted by var---as argument.

The variable bindings created are lexical unless special declarations are specified.

The forms are evaluated in order, and the values of all but the last are discarded (that is, the body is an implicit progn).


    (with-unique-names (sym1) sym1)  =>  #:SYM13142
    (with-unique-names ((sym1 "SYM1-")) sym1)  => #:SYM1-3143
    (find-symbol "SYM1-3143")  =>  NIL, NIL
    (with-unique-names ((sym #\Q)) sym) => #:Q3144
    (with-unique-names ((sym1 :sym1-)) sym1) => #:SYM1-3145
    (with-unique-names (sym1) (symbol-package sym1))  =>  NIL
    (with-unique-names (sym8) (eq sym8 sym8))  =>  T
    (with-unique-names (sym9) (set sym9 42) (symbol-value sym9))  =>  42

Side Effects:

Might increment *gensym-counter* once for each var.

Affected by: *gensym-counter*

Exceptional Situations: None.

See Also:

gensym, let, rebinding


Discussed on comp.lang.lisp in the thread starting with cy3eln0foea.fsf@ljosa.com. Suggested for inclusion in Common Lisp Utilities.

Reference Implementation:

(defmacro with-unique-names ((&rest bindings) &body body) `(let ,(mapcar #'(lambda (binding) (destructuring-bind (var prefix) (if (consp binding) binding (list binding binding)) `(,var (gensym ,(string prefix))))) bindings) ,@body))


Why was the name changed from the much more common WITH-GENSYMS? -DRC

The name WITH-UNIQUE-NAMES says what the macro is supposed to do, the name WITH-GENSYMS says how the macro is implemented which is irrelevant. (Besides, you don't have to do it with gensyms.)

Muddled thinking. You can't get away from GENSYMs without breaking the macro's contract. A no-no for library code. Therefore WITH-GENSYMS was a spot-on description of what the macro does and will remain so. All you managed to do was burn a more generic name forever while at the same time naming this macro with a less descriptive name.

You could do it with MAKE-SYMBOL along with some scheme for generating unique suffixes (imagine a call to uuidgen on Unix-y systems). So no, you don't need GENSYM. (No. What part of as if by call to gensym is that hard to understand?)

macro example