CommonLisp
Clojure
LispMacros
ClojureMacros
No problem in Lisp-2 (like
CommonLisp) - problem in Lisp-1 (like
Scheme).
Hygienic macros are macros whose expansion is guaranteed not to cause collisions with existing symbol definitions. [1]
An hygienic macro is one where the meanings of symbols that aren't parameters to the macro are bound at the de!nition site rather than the expansion site.
- Why Hygienic Macros Rock
- http://eli.thegreenplace.net/2007/09/16/common-lisp-vs-scheme-macros/
- easy to understand examples
- Problems with non-hygienic macros:
- What if function called in macro is rebound in calling context (by flet)?
- What if a global variable used in the macro is shadowed by the calling context?
- http://arclanguage.org/item?id=3422
- Also, one of the problems with Common-Lisp-like macros is variable capture, right? As in, a function gets shadowed by a local variable, so the macro ends up producing code that calls the wrong function or just fails. (Correct me if I'm saying this the wrong way or if I'm just plain wrong :)) But, couldn't this be solved with a module system?
I was thinking that with a Java-like package system, you could just refer to the function you actually mean. Like you can refer to classes by their full name package.name.ClassName?, you could refer to functions and macros the same way.
- ->Variable capture is a feature, not a bug. It happens only if the macro author wants it to (on pretty rare occasions) or if they need to be fired for not using gensym to create an uninterned symbol which cannot possibly clash with another name/symbol.
CommonLisp is a Lisp-2:
(let ( (list 42))
(list 'hi 'mom))
... works fine and produces '(HI MOM) because CL is a Lisp-2 and shrugs off the variable name (in the operator position, variables do not apply (ugh, pun not intended).
(defun xxx ()
(flet ((list (&rest args)
(car args)))
(list 'hi 'mom)))
; While compiling XXX in C:\DOCUME~1\Kenny\LOCALS~1\Temp\cda9402357291.cl:
Warning: Compiling a FUNCTION definition for the name LIST
as a FLET. This name is in the COMMON-LISP package and
defining it will be a violation for portable programs.
The package COMMON-LISP has PACKAGE-DEFINITION-LOCK set,
which causes the system to signal this violation.
- http://arclanguage.org/item?id=2962
- Hygienic macros are there to prevent accidental variable capture. (More precisely they prevent collisions of symbol definitions.)
In practice, it's very easy to avoid symbol collisions on local variables. In practice, it's harder to avoid collisions on global symbols like function names. (I'm using the "local" and "global" terms loosely here.)
- Scheme's macros appear to work differently from arc and CL's macros. Scheme macros use a special pattern language to describe the code transformations.
- In a Lisp 2 like Common Lisp it is very easy to work around name collisions problems with a module system. It's much harder to solve this problem in a Lisp 1 with just a module system. All the ways I know how to solve the collision problem in a Lisp 1 that use namespace management require integration with the macro expander.
- actually, arc does use the same namespace, that is most of the cause of this problem. if they were in different namespaces, there would be no problem with variables shadowing built-in functions. you still have to worry about variable capture, but it's a much less significant problem.
- The Adventures of a Pythonista in Schemeland/28: Hygienic macros