From: senator
Subject: Uninterned symbols at macroexpansion time.
Date: 
Message-ID: <1139635546.455289.89670@z14g2000cwz.googlegroups.com>
How does gensym works again?

I thought I understood it, but it looks like I haven't. I've used
with-unique-names (or with-gensyms or whatever) quite a few times, and
thought it was pretty straightforward, until I started to use gensym
for symbol generation in functions, ie non-macros. I started to wonder
why the uninterned symbol generated by gensym can be used repeatedly if
it was never interned (if it's always a new symbol)?

[10]> (defmacro test ()
  (let ((x (gensym)))
    `(loop for ,x in '(1 2 3)
           collect ,x)))
TEST

Just an example, nevermind that x cannot be (variable-)captured anyway,
so gensym is not really needed.

[11]> (test)
(1 2 3)


[12]> (macroexpand-1 '(test))
(LOOP FOR #:G2880 IN '(1 2 3) COLLECT #:G2880) ;
T

Copy and pasting the macroexpand-1'ed code back into the REPL doesn't
work.

[13]> (LOOP FOR #:G2880 IN '(1 2 3) COLLECT #:G2880)

*** - EVAL: variable #:G2880 has no value
The following restarts are available:
blah blah

Another similar test:

[23]> (let ((x (gensym))) (loop for `,x in (1 2 3) collect 1))

*** - EVAL: 1 is not a function name; try using a symbol instead

Not a very descriptive error, but I think this is due to the same
problems (loop macroexpansion probably got confused).


Manually typing an uninterned variable doesn't work either.
[33]> (defmacro test()
(let ((x #:aaa))
  `(loop for ,x in '(1 2 3) collect ,x)))
TEST
[34]> (test)

*** - EVAL: variable #:AAA has no value

So, to summarise my question, how can a gensymed variable be "referred
back to" in macros if (eq '#:foo '#:foo) ==> nil? I vaguely suspect a
few different combinations of things going on here, but have not got
anywhere in my pondering. Any hints?

Have a nice day.

From: Kaz Kylheku
Subject: Re: Uninterned symbols at macroexpansion time.
Date: 
Message-ID: <1139638862.308806.302050@z14g2000cwz.googlegroups.com>
senator wrote:
> How does gensym works again?

You call it, it allocates and returns a symbol. The symbol has a
generated name, but what makes it unique is its address. The name has
nothing to do with it.

> I thought I understood it, but it looks like I haven't. I've used
> with-unique-names (or with-gensyms or whatever) quite a few times, and
> thought it was pretty straightforward, until I started to use gensym
> for symbol generation in functions, ie non-macros. I started to wonder
> why the uninterned symbol generated by gensym can be used repeatedly if
> it was never interned (if it's always a new symbol)?
>
> [10]> (defmacro test ()
>   (let ((x (gensym)))
>     `(loop for ,x in '(1 2 3)
>            collect ,x)))

Here, the macro's lexical variable X hangs on to the gensym object. By
means of this variable, the same object is inserted in two places in
the backquoted template.

> [12]> (macroexpand-1 '(test))
> (LOOP FOR #:G2880 IN '(1 2 3) COLLECT #:G2880) ;
> T
>
> Copy and pasting the macroexpand-1'ed code back into the REPL doesn't
> work.

It doesn't work precisely because the #: notation specifies an
uninterned symbol. Here, you no longer have a mechanism which ensures
that the same object appears in two places in a form. That mechanism is
interning!!!

Each time the reader reads a #:<IDENT> symbol, it behaves as if it
internally called MAKE-SYMBOL. That is, (MAKE-SYMBOL "G2880") is called
twice, resulting in two uninterned symbols (which have the same name).
No further use is made of that name. It's not entered into any package,
of course. It's just used for printing the symbol.

If you want to print a form that contains uninterned symbols, such that
it can be read back, you have to set *PRINT-CIRCLE* to T. Then you will
get something like

  (LOOP FOR #1=#:G2880 IN '(1 2 3) COLLECT #1#)

The reader now sticks the same object in two places by means of the #1=
 definition and #1# reference.

> [13]> (LOOP FOR #:G2880 IN '(1 2 3) COLLECT #:G2880)
>
> *** - EVAL: variable #:G2880 has no value
> The following restarts are available:
> blah blah
>
> Another similar test:
>
> [23]> (let ((x (gensym))) (loop for `,x in (1 2 3) collect 1))
>
> *** - EVAL: 1 is not a function name; try using a symbol instead
>
> Not a very descriptive error, but I think this is due to the same
> problems (loop macroexpansion probably got confused).

No, that error is due to not quoting the (1 2 3).  But the `,x is
definitely wrong. You can't use a backquote there because the argument
to FOR isn't evaluated.

You end up with a backquote object as the variable specification.

> Manually typing an uninterned variable doesn't work either.
> [33]> (defmacro test()
> (let ((x #:aaa))
>   `(loop for ,x in '(1 2 3) collect ,x)))
> TEST
> [34]> (test)
>
> *** - EVAL: variable #:AAA has no value

You forgot to put a quote in front of the #:AAA.  This will work just
fine.

Of course, each expansion of the macro now uses the same #:AAA object.
That's okay; it can't cause any problems.
From: Brian Downing
Subject: Re: Uninterned symbols at macroexpansion time.
Date: 
Message-ID: <8nfHf.548938$084.477582@attbi_s22>
In article <·······················@z14g2000cwz.googlegroups.com>,
senator <···············@gmail.com> wrote:
> [12]> (macroexpand-1 '(test))
> (LOOP FOR #:G2880 IN '(1 2 3) COLLECT #:G2880) ;
> T
> 
> Copy and pasting the macroexpand-1'ed code back into the REPL doesn't
> work.
> 
> [13]> (LOOP FOR #:G2880 IN '(1 2 3) COLLECT #:G2880)
> 
> *** - EVAL: variable #:G2880 has no value

Observe:

CL-USER> (defmacro test ()
           (let ((x (gensym)))
             `(loop for ,x in '(1 2 3) collect ,x)))
TEST
CL-USER> (test)
(1 2 3)
CL-USER> (macroexpand-1 '(test))
(LOOP FOR #:G1223 IN '(1 2 3) COLLECT #:G1223)
T
CL-USER> (setf *print-circle* t)
T
CL-USER> (macroexpand-1 '(test))
(LOOP FOR #1=#:G1224 IN '(1 2 3) COLLECT #1#)
T
CL-USER> '(LOOP FOR #:G1223 IN '(1 2 3) COLLECT #:G1223)
(LOOP FOR #:G1223 IN '(1 2 3) COLLECT #:G1223)

See the difference?  If not, try this:

CL-USER> (eq '#:g1223 '#:g1223)
NIL
CL-USER> (let ((sym '#:g1223))
           (eq sym sym))
T

-bcd
-- 
*** Brian Downing <bdowning at lavos dot net> 
From: Pascal Bourguignon
Subject: Re: Uninterned symbols at macroexpansion time.
Date: 
Message-ID: <878xsih14i.fsf@thalassa.informatimago.com>
"senator" <···············@gmail.com> writes:

> How does gensym works again?

It works like this:

(let ((counter 0))
  (defun gensym (&optional (prefix "G"))
     (make-symbol (format nil "~A~A" prefix (incf counter)))))



> I thought I understood it, but it looks like I haven't. I've used
> with-unique-names (or with-gensyms or whatever) quite a few times, and
> thought it was pretty straightforward, until I started to use gensym
> for symbol generation in functions, ie non-macros. I started to wonder
> why the uninterned symbol generated by gensym can be used repeatedly if
> it was never interned (if it's always a new symbol)?

Because symbols are searched (by FIND-SYMBOL, via INTERN) only when
read, not when processed by the compiler or interpreter.  That's the
point of having a s-expr for syntax tree: you don't have to search
names in a symbol table because you already have the pointers to the
symbols.  If these symbols are interned in a package or not doesn't
matter at all.

> [10]> (defmacro test ()
>   (let ((x (gensym)))
>     `(loop for ,x in '(1 2 3)
>            collect ,x)))
> TEST
>
> Just an example, nevermind that x cannot be (variable-)captured anyway,
> so gensym is not really needed.
>
> [11]> (test)
> (1 2 3)


The code generate by the macro IS NEVER READ!


> [12]> (macroexpand-1 '(test))
> (LOOP FOR #:G2880 IN '(1 2 3) COLLECT #:G2880) ;
> T
>
> Copy and pasting the macroexpand-1'ed code back into the REPL doesn't
> work.
>
> [13]> (LOOP FOR #:G2880 IN '(1 2 3) COLLECT #:G2880)
>
> *** - EVAL: variable #:G2880 has no value

Obviously, when you read #:xxx you're instructing the reader to call
MAKE-SYMBOL everytime.  Try:

[125]> (setf *print-circle* t)
T
[126]> (macroexpand-1 '(test))
(LOOP FOR #1=#:G18804 IN '(1 2 3) COLLECT #1#) ;
T
[127]> (LOOP FOR #1=#:G18804 IN '(1 2 3) COLLECT #1#) 
(1 2 3)
[128]> 




> [23]> (let ((x (gensym))) (loop for `,x in (1 2 3) collect 1))
>
> *** - EVAL: 1 is not a function name; try using a symbol instead
>
> Not a very descriptive error, but I think this is due to the same
> problems (loop macroexpansion probably got confused).

No, this is something completely different.  1 is not a function name.
You should try to use a symbol instead.  Like LIST:


(let ((x (gensym))) (loop for `,x in (LIST 1 2 3) collect 1))


Then you encounter an error completely different because you didn't
give a list of lists:

(let ((x (gensym)))
    (loop for `,x in '((1 (2 3)) (11 (22 33)) (111 (222 333))) 
          collect #+clisp system::backquote 
                  #-clisp (error "I don't know what reading `x produces 
                                  on your system.")))
(1 11 111)


> Manually typing an uninterned variable doesn't work either.
> [33]> (defmacro test()
> (let ((x #:aaa))
>   `(loop for ,x in '(1 2 3) collect ,x)))
> TEST
> [34]> (test)
>
> *** - EVAL: variable #:AAA has no value

What did you expect?    If you want to bind x to a symbol, why are you
trying to bind it to the value of the variable #:AAA?

(let ((x '#:aaa)) ; anybody?
   ...)


> So, to summarise my question, how can a gensymed variable be "referred
> back to" in macros if (eq '#:foo '#:foo) ==> nil? 

With references.  The following is always true: (eq x x)
whatever the value of x.  (let ((x '#:foo)) (eq x x)) --> T

> I vaguely suspect a
> few different combinations of things going on here, but have not got
> anywhere in my pondering. Any hints?

Remeber: the source of a lisp program is not a text file, it's a data
structure, with pointers and shared substructures.  Some parts of this
data structure may come from the reader, some may come from the
execution of macros, some can even be generated at compilation-time
(compiler macros) or at run-time.

-- 
__Pascal Bourguignon__                     http://www.informatimago.com/

HANDLE WITH EXTREME CARE: This product contains minute electrically
charged particles moving at velocities in excess of five hundred
million miles per hour.
From: Peter Seibel
Subject: Re: Uninterned symbols at macroexpansion time.
Date: 
Message-ID: <m2u0b655rv.fsf@gigamonkeys.com>
Pascal Bourguignon <······@informatimago.com> writes:

> The following is always true: (eq x x) whatever the value of x.

No, (eql x x) is always true whatever the value of X. (eq x x) can be
true or false if the value of X is a character or number.

-Peter

-- 
Peter Seibel           * ·····@gigamonkeys.com
Gigamonkeys Consulting * http://www.gigamonkeys.com/
Practical Common Lisp  * http://www.gigamonkeys.com/book/
From: Wade Humeniuk
Subject: Re: Uninterned symbols at macroexpansion time.
Date: 
Message-ID: <M3pHf.2124$Be4.1976@clgrps13>
Peter Seibel wrote:
> Pascal Bourguignon <······@informatimago.com> writes:
> 
>> The following is always true: (eq x x) whatever the value of x.
> 
> No, (eql x x) is always true whatever the value of X. (eq x x) can be
> true or false if the value of X is a character or number.
> 

There is always an exception to the rule,


CL-USER 13 > (defparameter *x* 0)
*X*

CL-USER 14 > (define-symbol-macro x (prog1 *x* (incf *x*)))
(PROG1 *X* (INCF *X*))

CL-USER 15 > (eql x x)
NIL

CL-USER 16 >

Wade
From: Pascal Bourguignon
Subject: Re: Uninterned symbols at macroexpansion time.
Date: 
Message-ID: <87r769g17l.fsf@thalassa.informatimago.com>
Peter Seibel <·····@gigamonkeys.com> writes:

> Pascal Bourguignon <······@informatimago.com> writes:
>
>> The following is always true: (eq x x) whatever the value of x.
>
> No, (eql x x) is always true whatever the value of X. (eq x x) can be
> true or false if the value of X is a character or number.

(eq x x) is always true.

Think about the work an implementation would have to do to return:
(let ((x #\a)) (eq x x)) --> NIL

hint: (defun eq (x y) ...)

-- 
__Pascal Bourguignon__                     http://www.informatimago.com/

"Debugging?  Klingons do not debug! Our software does not coddle the
weak."
From: Peter Seibel
Subject: Re: Uninterned symbols at macroexpansion time.
Date: 
Message-ID: <m2lkwh64mg.fsf@gigamonkeys.com>
Pascal Bourguignon <······@informatimago.com> writes:

> Peter Seibel <·····@gigamonkeys.com> writes:
>
>> Pascal Bourguignon <······@informatimago.com> writes:
>>
>>> The following is always true: (eq x x) whatever the value of x.
>>
>> No, (eql x x) is always true whatever the value of X. (eq x x) can be
>> true or false if the value of X is a character or number.
>
> (eq x x) is always true.

Not according to the standard. Okay, so it's not normative but this is
one of the examples from the EQ dictionary entry:

 (let ((x 5)) (eq x x)) 
   =>  true
 OR=>  false

> Think about the work an implementation would have to do to return:
> (let ((x #\a)) (eq x x)) --> NIL

The thing that make (eq x x) possibly be NIL has nothing to do with
the implementation of EQ but with the lattitude the implementation has
to make copies of characters and numbers at any time. I'm not saying
it's likely or that any implementation actually does this but on needs
to be aware of the possibility if one wants to write strictly correct
code.

-Peter

-- 
Peter Seibel           * ·····@gigamonkeys.com
Gigamonkeys Consulting * http://www.gigamonkeys.com/
Practical Common Lisp  * http://www.gigamonkeys.com/book/
From: Coby Beck
Subject: Re: Uninterned symbols at macroexpansion time.
Date: 
Message-ID: <ZcsHf.6534$W31.4697@edtnps90>
"Peter Seibel" <·····@gigamonkeys.com> wrote in message 
···················@gigamonkeys.com...
> Pascal Bourguignon <······@informatimago.com> writes:
>
>> Peter Seibel <·····@gigamonkeys.com> writes:
>>
>>> Pascal Bourguignon <······@informatimago.com> writes:
>>>
>>>> The following is always true: (eq x x) whatever the value of x.
>>>
>>> No, (eql x x) is always true whatever the value of X. (eq x x) can be
>>> true or false if the value of X is a character or number.
>>
>> (eq x x) is always true.
>
> Not according to the standard. Okay, so it's not normative but this is
> one of the examples from the EQ dictionary entry:
>
> (let ((x 5)) (eq x x))
>   =>  true
> OR=>  false
>
>> Think about the work an implementation would have to do to return:
>> (let ((x #\a)) (eq x x)) --> NIL
>
> The thing that make (eq x x) possibly be NIL has nothing to do with
> the implementation of EQ but with the lattitude the implementation has
> to make copies of characters and numbers at any time. I'm not saying
> it's likely or that any implementation actually does this but on needs
> to be aware of the possibility if one wants to write strictly correct
> code.

Peter is of course right.  In short, EQL will do everything you want EQ to 
do and has no "gotchas".  So what's the lesson?  Never use EQ, always use 
EQL and never worry about these nasties again.

-- 
Coby Beck
(remove #\Space "coby 101 @ bigpond . com")
From: Pascal Bourguignon
Subject: Re: Uninterned symbols at macroexpansion time.
Date: 
Message-ID: <877j8034yq.fsf@thalassa.informatimago.com>
Peter Seibel <·····@gigamonkeys.com> writes:

> Pascal Bourguignon <······@informatimago.com> writes:
>
>> Peter Seibel <·····@gigamonkeys.com> writes:
>>
>>> Pascal Bourguignon <······@informatimago.com> writes:
>>>
>>>> The following is always true: (eq x x) whatever the value of x.
>>>
>>> No, (eql x x) is always true whatever the value of X. (eq x x) can be
>>> true or false if the value of X is a character or number.
>>
>> (eq x x) is always true.
>
> Not according to the standard. Okay, so it's not normative but this is
> one of the examples from the EQ dictionary entry:
>
>  (let ((x 5)) (eq x x)) 
>    =>  true
>  OR=>  false
>
>> Think about the work an implementation would have to do to return:
>> (let ((x #\a)) (eq x x)) --> NIL
>
> The thing that make (eq x x) possibly be NIL has nothing to do with
> the implementation of EQ but with the lattitude the implementation has
> to make copies of characters and numbers at any time. I'm not saying
> it's likely or that any implementation actually does this but on needs
> to be aware of the possibility if one wants to write strictly correct
> code.

All right.  I need to read CLHS once more.

-- 
__Pascal Bourguignon__                     http://www.informatimago.com/
In deep sleep hear sound,
Cat vomit hairball somewhere.
Will find in morning.
From: senator
Subject: Re: Uninterned symbols at macroexpansion time.
Date: 
Message-ID: <1139885431.630606.272860@g43g2000cwa.googlegroups.com>
Thanks to all Lispers who replied. I think I can see my
code slightly more clearly now (still re-reading all
your posts). Some more questions (slightly
off-topic) and comments in the following.

Yes, I meant to quote the list here (oopsies) '(1 2 3),
but why doesn't it work still?

> > [23]> (let ((x (gensym))) (loop for `,x in (1 2 3)
>   collect 1))
...etc

So what is actually happening here? Is it not
equivalent to

(loop for somevar in '(some list here) collect somevar)?

Or am I looking at "undefined" interactions with the
loop macro? somevar should just a symbol right? I might
have seen the loop macro convert them to gensyms, if
I'm not mistaken, so if we give the macro a gensym in
the first place .... the world explodes?!!

>
> (let ((x (gensym))) (loop for `,x in (LIST 1 2 3)
> collect 1))
>
> Then you encounter an error completely different
> because you didn't give a list of lists:
>
> (let ((x (gensym)))
>   (loop for `,x in '((1 (2 3)) (11 (22 33)) (111 (222 333)))
> 	collect #+clisp	system::backquote
> 		#-clisp (error "I don't know what
> 		    reading `x produces on your system.")))
> (1 11 111)
>
>
No, I cannot see what this does. Some tidying up: (I am
using clisp)

[50]> (let ((x (gensym)))
    (loop for `,x in '((1 (2 3)) (11 (22 33)) (111 (222 333)))
          collect system::backquote))
(1 11 111)

Or this one:

[51]> (let ((x (gensym)))
    (loop for `,x in '((1 (2 3)) (11 (22 33)) (111 (222 333)))
          collect `,x))
(3 33 333)

Makes no sense at all.

This next one has a slip-up too.
> > (let ((x #:aaa))

Indeed, an extra quote is needed. Sorry about that.

>
>
> With references.  The following is always true: (eq x
> x) whatever the value of x.  (let ((x '#:foo)) (eq x
> x)) --> T
>

Another offtopic question, here I'm quoting Coby Beck
replying Peter Seibel:

> Peter is of course right.  In short, EQL will do
> everything you want EQ to do and has no "gotchas".  So
> what's the lesson?  Never use EQ, always use EQL and
> never worry about these nasties again.

If we are going to talk about the most simplistic and
general equal, why not just use "equal" (for every
simple type (meaning eg symbols, lists, etc) not
counting numbers or strings)?

; ----- After another day playing around --------
Ok, I've played around a bit more, and am happy with
what I know about this business with the symbol objects
themselves, and their string representations (which is
what we see, and what we give the reader). Basically,
what I was trying to do (I haven't shown that in my
queries) was trying to bypass the reader when using
gensym, but I didn't realise I was already doing that
in my code. Gotta be careful when playing in the REPL,
it's not exactly the same sometimes...

Thanks again everyone, till we meet again (with
another silly question of mine)
From: Pascal Bourguignon
Subject: Re: Uninterned symbols at macroexpansion time.
Date: 
Message-ID: <87u0b2y0ct.fsf@thalassa.informatimago.com>
"senator" <···············@gmail.com> writes:
> [...]
> So what is actually happening here? Is it not
> equivalent to
>
> (loop for somevar in '(some list here) collect somevar)?

No.

 (loop for somevar in '(1 2 3)          collect 1)
 (loop for somevar in '(some list here) collect somevar)?

In the first case, you're collecting the literal 1 once for each
element of the list, it's equivalent to:
   (make-list (length '(1 2 3) :initial-element 1)
while in the second, you're collecting each element of the list, making
it equivalent to: (copy-list '(some list here))

You won't make a lot of progress with computers if you are not
extra-careful with all the details.

At the same time, it is good to have some "peripheral" vision.  Either
when you're watching your program, or when you're reading the
newsgroups.  The answer to your question has been discussed in
details, but in another thread!


> Or am I looking at "undefined" interactions with the
> loop macro?

No.

> somevar should just a symbol right? 

Yes.

> I might have seen the loop macro convert them to gensyms, if
> I'm not mistaken, so if we give the macro a gensym in
> the first place .... the world explodes?!!

The problem is not here.


>> (let ((x (gensym))) (loop for `,x in (LIST 1 2 3)
>> collect 1))
>>
>> Then you encounter an error completely different
>> because you didn't give a list of lists:
>>
>> (let ((x (gensym)))
>>   (loop for `,x in '((1 (2 3)) (11 (22 33)) (111 (222 333)))
>> 	collect #+clisp	system::backquote
>> 		#-clisp (error "I don't know what
>> 		    reading `x produces on your system.")))
>> (1 11 111)
>>
>>
> No, I cannot see what this does. Some tidying up: (I am
> using clisp)

Watch carefully the details!  What is this system::backquote symbol?
Where does it come from?  Watch the error message programmed for
non-clisp implementations.  What does it tell you?  


> [50]> (let ((x (gensym)))
>     (loop for `,x in '((1 (2 3)) (11 (22 33)) (111 (222 333)))
>           collect system::backquote))
> (1 11 111)
>
> Or this one:
>
> [51]> (let ((x (gensym)))
>     (loop for `,x in '((1 (2 3)) (11 (22 33)) (111 (222 333)))
>           collect `,x))
> (3 33 333)
>
> Makes no sense at all.


LOOP is a macro.  It doesn't evaluate most of its arguments.  The
syntax of LOOP includes a grammar rule that say that after FOR you can
have either a symbol naming a variable (what you'd want), or a list of
symbols or sublists to be used as a pattern to destructure the
elements of  the list given after IN, and to bind to the variables
namedby these symbols:

[23]> (loop for x in '(1 2 3) do (print x))

1 
2 
3 
NIL
[24]> (loop for (n (eng fre)) in '((1 (one un)) (2 (two deux)) (3 (three trois)))
             do (format t "~A (~A) is ~A~%" eng fre n))
ONE (UN) is 1
TWO (DEUX) is 2
THREE (TROIS) is 3
NIL


Now, when you type: `,x
the clisp reader returns, well, it's implementation dependant, so let's ask it:


(defun print-conses (tree &optional (stream *standard-output*))
  ;; WARNING: doesn't handle circles nor identify EQ subtrees.
  (cond
   ((null tree) (princ "()"))
   ((atom tree)  (princ tree stream) (princ " " stream))
   (t (princ "(" stream) 
      (print-conses (car tree) stream)
      (princ " . " stream)
      (print-conses (cdr tree) stream)
      (princ ")" stream)))
  tree)


[32]> (print-conses (read))                       ; input to the Repl
`,x                                               ; input to READ
(BACKQUOTE  . ((UNQUOTE  . (X  . ())) . ()))      ; printed by print-conses
`,X                                               ; printed by the rePl

So what is actually read when you type `,x is a list of two elements,
the first being the symbol SYSTEM::BACKQUOTE, and the second a list of
two elements, the first being the symbol SYSTEM::UNQUOTE and the second
the symbol X:

  (BACKQUOTE (UNQUOTE  X))

or, when all the conses are explicited:

  (BACKQUOTE  . ((UNQUOTE  . (X  . ())) . ()))


So when you read this form:

  (let ((x (gensym)))
     (loop for `,x in '((1 (2 3)) (11 (22 33)) (111 (222 333)))
           collect `,x))

what the EVAL function is exactly this:

(let ((x (gensym)))
     (loop for (BACKQUOTE (UNQUOTE  X)) 
            in (QUOTE ((1 (2 3)) (11 (22 33)) (111 (222 333))))
       collect (BACKQUOTE (UNQUOTE  X))))

To evaluate this form, EVAL identifies LET as a special operator, then
LOOP as a macro, and therefore doesn't evaluate anything inside the
(LOOP ...) list, but pass everything to the LOOP macro as is.

The LOOP macro seens that you typed FOR (BACKQUOTE (UNQUOTE  X)) IN
and therefore it knows it will bind three variables, BACKQUOTE,
UNQUOTE, and X to three parts of each elements of the list.

The form after IN is evaluated, but since it's (QUOTE ...), the list
inside the special form QUOTE is returned unevaluated and 
((1 (2 3)) (11 (22 33)) (111 (222 333))) is used to enumerate its elements.

The first iteration, 1 is bound to BACKQUOTE, 2 is bound to UNQUOTE
and 3 is bound to X.

The second iteration, 11 is bound to BACKQUOTE, 22 is bound to UNQUOTE
and 33 is bound to X.

etc.

Finally, the form after COLLECT is evaluated to know what to collect,
and EVAL notice that BACKQUOTE is a macro, therefore it calls its
macro function without evaluating the arguments (UNQUOTE X): the
BACKQUOTE macro expands to: X

[48]> (macroexpand-1 '(system::backquote (system::unquote x)))
X ;
T

Therefore  the value that is collected is the one that's bound to X,
inside the loop, that is, 3, 33, etc.




In conclusion, the problem is that you never gave a symbol for the
iteration variable to LOOP in the first place!  It doesn't matter for
a variable name if a symbol is interned or not.  A symbol produced by
GENSYM is a symbol like any other.  If you gave to LOOP a symbol
produced by GENSYM there would be no problem.  But you didn't!  You
gave a list.


You can give a symbol produced by gensym to LOOP:

(defmacro collect-items-with-loop (list)
  (let ((x (gensym)))
    `(loop for ,x in ,list collect ,x)))


[57]> (setf *print-circle* t)
T
[58]> (macroexpand-1 '(collect-items-with-loop '(1 2 3)))
(LOOP FOR #1=#:G8698 IN '(1 2 3) COLLECT #1#) ;
T
[59]> (collect-items-with-loop '(1 2 3))
(1 2 3)



If you want to write this LOOP directly in your source, instead of
introducing it with a macro, you need to compute the GENSYM symbol at
read-time:


[60]> (loop for #1=#.(gensym) in '(1 2 3) collect #1#)
(1 2 3)


Of course, there's no difference between a symbol produced by GENSYM
and one produced by MAKE-SYMBOL, so you can also let the lisp reader
produce un-interned symbols:

[61]> (loop for #1=#:un-interned in '(1 2 3) collect #1#)
(1 2 3)

[The later form is equivalent to:
  (loop for #1=#.(make-symbol "UN-INTERNED") in '(1 2 3) collect #1#)
]



In both cases, since you cannot "read" twice the same un-interned
symbol, you need to use the #1=... #1# trick to have the reader insert
twice the same symbol in the s-expr the reader builds.




>> With references.  The following is always true: (eq x
>> x) whatever the value of x.  (let ((x '#:foo)) (eq x
>> x)) --> T
>
> Another offtopic question, here I'm quoting Coby Beck
> replying Peter Seibel:
>
>> Peter is of course right.  In short, EQL will do
>> everything you want EQ to do and has no "gotchas".  So
>> what's the lesson?  Never use EQ, always use EQL and
>> never worry about these nasties again.

Ok, I was wrong, the standard seems in effect to give the freedom to
an implementation to _copy_ a character (or number) when passing it as
an argument, and to compare the "address" of the characters in EQ, in
which case (let ((x #\a)) (eq x x)) could return NIL.  It sounds
rather improbable, and not what was intended to be specified IMHO, but
so is the letter.


> If we are going to talk about the most simplistic and
> general equal, why not just use "equal" (for every
> simple type (meaning eg symbols, lists, etc) not
> counting numbers or strings)?

The point is that here we are considering symbols. For symbols, EQ,
EQL, EQUAL and EQUALP are equivalent.

For cons cells, that is for lists, EQL and EQUAL are different.   
EQL tests for the identity of the cons cell, in O(1), while
EQUAL compares the elements in the tree, in O(n), and without handing
circular structures.

(eql   '#1=(#1# . #1#) '#2=(#2# . #2#)) --> NIL
(equal '#1=(#1# . #1#) '#2=(#2# . #2#)) --> stack overflow



-- 
__Pascal Bourguignon__                     http://www.informatimago.com/
Until real software engineering is developed, the next best practice
is to develop with a dynamic system that has extreme late binding in
all aspects. The first system to really do this in an important way
is Lisp. -- Alan Kay
From: senator
Subject: Re: Uninterned symbols at macroexpansion time.
Date: 
Message-ID: <1139960570.977937.234490@z14g2000cwz.googlegroups.com>
> (loop for somevar in '(some list here) collect somevar)?
> No.
>
>  (loop for somevar in '(1 2 3)          collect 1)
>  (loop for somevar in '(some list here) collect somevar)?
>
> In the first case, you're collecting the literal 1 once for each
> element of the list, it's equivalent to:
>    (make-list (length '(1 2 3) :initial-element 1)
> while in the second, you're collecting each element of the list, making
> it equivalent to: (copy-list '(some list here))


> You won't make a lot of progress with computers if you are not
> extra-careful with all the details.

Of course, by equivalent, I don't mean exactly the same ->
you all know that I was talking about the equivalence
between "`,x" (in previous posts) and "somevar" right? The
collecting was not really what I was worried about.

I didn't have the whole Lisp/Slime/Emacs etc setup at work,
so I was typing things up, copying and pasting into dos REPL
(getting bitten by spurious character insertion bugs) so it
can be hard maintaining perfection here. :)

>
> At the same time, it is good to have some "peripheral" vision.  Either
> when you're watching your program, or when you're reading the
> newsgroups.  The answer to your question has been discussed in
> details, but in another thread!

Yes, I think it's that quasiquotation thread. It's
connecting the dots that's the hard bit.

> > [50]> (let ((x (gensym)))
> >     (loop for `,x in '((1 (2 3)) (11 (22 33)) (111 (222 333)))
> >           collect system::backquote))
> > (1 11 111)
>
> > Or this one:
>
> > [51]> (let ((x (gensym)))
> >     (loop for `,x in '((1 (2 3)) (11 (22 33)) (111 (222 333)))
> >           collect `,x))
> > (3 33 333)
>

So it's destructuring-bind (within loop) + reader expansion
of quasiquotations + selective evaluation (loop) interacting
here. Magic! All your posts (especially Pascal) have been
most instructive, thanks a lot.
From: Frank Buss
Subject: Re: Uninterned symbols at macroexpansion time.
Date: 
Message-ID: <1v6a8rx8ig470$.1xjp4qr5sgxrt.dlg@40tude.net>
Pascal Bourguignon wrote:

> (eq x x) is always true.

a simpler example like Wade wrote:

CL-USER > (define-symbol-macro x (gensym))
CL-USER > (eq x x)
NIL

-- 
Frank Buss, ··@frank-buss.de
http://www.frank-buss.de, http://www.it4-systems.de