sperber(a)Informatik.Uni-Tuebingen.De (Michael Sperber [Mr. Preprocessor]) writes:
>>>>> "Clemens" == Clemens Heitzinger
<cheitzin(a)rainbow.studorg.tuwien.ac.at> writes:
Clemens> sperber(a)informatik.uni-tuebingen.de (Michael Sperber [Mr. Preprocessor])
writes:
>> Sure, but there's no guarantee that a given macro has hygienic
>> behavior. Generally, maintaining hygiene this way is pretty tedious,
>> which is why programmers usually don't go to the necessary lengths.
>>
>> Also, a macro might refer to bindings whose names are free in the
>> macro definition. There's no guarantee that you'll get the same
>> bindings for a use that you referred to at the point of definition.
Clemens> Maintaining hygiene is *not* pretty tedious. If you want your CL macro
Clemens> to be hygienic, use
Clemens> (defmacro with-hygienic-variables (var &body body)
Clemens> `(let ,(loop for var in vars collect
Clemens> `(,var (make-symbol ,(symbol-name var))))
Clemens> ,@body))
I'm not sure what you're trying to do. The macro, as it stands, is
buggy. I assume you mean "vars" instead of "var" in the argument
list.
Obviously yes, sorry for any confusion.
Even then, it's not clear what you're trying to do. It looks
just
like some syntactic sugar around renaming variables.
Fresh uninterned symbols are made and bound to prevent unintended
variable capture. According to the HyperSpec (see make-symbol),
(eq (make-symbol "foo") (make-symbol "foo"))
=> nil
What do you mean, "syntactic sugar"? Are macros syntactic sugar?
Clemens> Therefore, in situations where non-hygienic macros have
advantages,
Clemens> use a non-hygienic macro. When you want hygienic variables, use the
Clemens> macro above (or write your own define-hygienic-macro, which uses the
Clemens> above). It is as simple as that.
Unfortunately, no. If used correctly, WITH-HYGIENIC-VARIABLES, can
only prevent inadvertent capture problems. To do this, you still
have to list the variables to be renamed explicitly, and you still
need to get the unquoting right to actually make use of them. Thus,
it makes maintaining hygiene only marginally easier. You still need
all annotations you needed originally, they just become smaller.
Look at the example below. The definition of define-hygienic-macro is
quite straight-forward, and it's use isn't difficult, either.
(defmacro with-hygienic-variables (vars &body body)
`(let ,(loop for var in vars collect
`(,var (make-symbol ,(symbol-name var))))
,@body))
(defmacro define-hygienic-macro (name lambda-list hygienic-vars &body body)
`(defmacro ,name ,lambda-list
(with-hygienic-variables ,hygienic-vars
,@body)))
(defmacro foo0 (x)
`(loop for n from 1 to 10
collect n collect ,x))
(defmacro foo1 (x)
(with-hygienic-variables (n)
`(loop for ,n from 1 to 10
collect ,n collect ,x)))
(define-hygienic-macro foo2 (x)
(n)
`(loop for ,n from 1 to 10
collect ,n collect ,x))
(let ((n 0))
(foo0 (setq n 10)))
=> (1 10)
(let ((n 0))
(foo1 (setq n 10)))
=> (1 10 2 10 3 10 4 10 5 10 6 10 7 10 8 10 9 10 10 10)
(let ((n 0))
(foo2 (setq n 10)))
=> (1 10 2 10 3 10 4 10 5 10 6 10 7 10 8 10 9 10 10 10)
Hygiene, however, means that variables in macros obey the same
scoping
rules as the rest of the language. WITH-HYGIENIC-VARIABLES gives you
no help whatsoever referring to lexical bindings of the macro. CL
What help do you mean?
macros are not hygienic, period.
Nobody claimed that. I wanted to make the point that it is quite easy
to define hygienic macros in CL.
Yours,
--
Clemens Heitzinger
Student der Techn. Mathematik, Technische Universität Wien, Österreich
Vienna University of Technology, Austria