In CL, macros are simply source-to-source transformations. If the
expansion introduces new variables, they're visible to any code that came
from the subforms in the macro invocation, and they can hide its own
variables. Consider the following:
(let ((i 4))
(repeat 10 (print i)))
You would expect this to print 10 lines containing "4". But suppose the
definition of REPEAT were:
(defmacro repeat (n-times &body body)
`(dotimes (i ,n-times)
,@body))
The expansion of the original form then becomes:
(let ((i 4))
(dotimes (i 10)
(print i)))
Which will print the numbers from 0 to 9, not what was intended.
Basically, unhygienic macros violate lexical scoping, since some variables
used internally within the macro are apparent to the user.
In CL, it's the programmer's responsibility to work around this. Common
techniques are using GENSYM:
(defmacro repeat (n-times &body body)
(let ((var (gensym)))
`(dotimes (,var ,n-times)
,@body)))
or function-passing:
(defun repeat-helper (n-times thunk)
(dotimes (i n-times)
(funcall thunk)))
(defmacro repeat (n-times &body body)
`(repeat-helper ,n-times (lambda () ,@body)))
>Semi-encrypted email address: m_b_p_o_m_i_j_e_ a_t_ i_n_a_v_ d_o_t_
>n_e_t_
Why do you encrypt your address in the text when the correct address is in
your header? Most address harvesters look in the header.
--
Barry Margolin, bar...@bbnplanet.com
GTE Internetworking, Powered by BBN, Cambridge, MA
*** DON'T SEND TECHNICAL QUESTIONS DIRECTLY TO ME, post them to newsgroups.
Barry Margolin has answered with the reasons why you need it, but Kent
Pitman posted an article some time ago (1998-03-20) that shed light on
why this is a serious problem in Scheme and no big deal in Common Lisp.
it's message-id is <sfwiupa...@world.std.com>¹ in reply to my
question in <30993159...@naggum.no>². (you should be able to find
them on Dejanews or other USENET search engines, too.)
in brief, Scheme has only one namespace, and the first element of an
s-expression is evaluated to obtain the function to call or the special
form. this means you run into a serious danger of using _functions_ that
have their meanings changed by the body of code into which the macro
expansion is "inserted". clearly, this is bad, but it's a design choice
in Scheme with many qualities, so they had to find a way to deal with it.
the way I see it (after reading and appreciating Kent's article) is that
Scheme allows a level of pollution that is unhealthy and then they need a
way to clean up, or things get "unhygienic" around them. Common Lisp is
hygienic _enough_ on its own since it doesn't pollute its namespaces to
begin with, and therefore need a simpler mechanism for variable capture.
#:Erik
-------
¹ src.naggum.no/lisp/news/sfwiupa...@world.std.com (http/ftp)
² src.naggum.no/lisp/news/30993159...@naggum.no (http/ftp)
--
"Where do you want to go to jail today?"
-- U.S. Justice Department's Windows 98 slogan