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