Newsgroups: comp.lang.lisp
Path: utzoo!utgpu!news-server.csri.toronto.edu!rpi!think.com!barmar
From: barmar@think.com (Barry Margolin)
Subject: Re: macro misbehaviour
Message-ID: <1991Jun9.141232.25632@Think.COM>
Sender: news@Think.COM
Reply-To: barmar@think.com
Organization: Thinking Machines Corporation, Cambridge MA, USA
References: <16456.285261a2@levels.sait.edu.au>
Date: Sun, 9 Jun 91 14:12:32 GMT
Lines: 40

In article <16456.285261a2@levels.sait.edu.au> Jenny.Rowland@levels.sait.edu.au writes:
>    (DEFMACRO TRY (X) (LET ((A (EVAL X))) `(TT ,(MAPCAR #'ADD-1 A))))
>    (DEFUN ADD-1 (X) (1+ X))
>    (DEFMACRO TT (X) `(FORMAT T "~a ~%" ',X))
>   (dotimes (n 3)
>     (let ((a (list n n n)))
>       (try a)))
>
>I get the following results:
>
>   (1 1 1)
>   (1 1 1)
>   (1 1 1)
>
>when I would expect:
>
>   (1 1 1)
>   (2 2 2)
>   (3 3 3)

The problem is your use of EVAL.  I'm surprised you didn't get an unbound
variable error regarding A; I suspect you had previously done

	(setq a '(0 0 0))

Unless you proclaim A special, LET binds it as a lexical variable.  EVAL
operates in the null lexical environment, so it isn't affected by this
binding.

However, even if you were to proclaim it special you might see this kind of
behavior.  Compilers must, and some interpreters do, expand macros before
executing any of the code.  Thus, the macro would be evaluated prior to
binding the variable in the LET.

This is why it is almost always wrong to use EVAL in macros.
-- 
Barry Margolin, Thinking Machines Corp.

barmar@think.com
{uunet,harvard}!think!barmar
