Open main menu
Home
Random
Recent changes
Special pages
Community portal
Preferences
About Wikipedia
Disclaimers
Incubator escapee wiki
Search
User menu
Talk
Dark mode
Contributions
Create account
Log in
Editing
Hygienic macro
(section)
Warning:
You are not logged in. Your IP address will be publicly visible if you make any edits. If you
log in
or
create an account
, your edits will be attributed to your username, along with other benefits.
Anti-spam check. Do
not
fill this in!
==The hygiene problem== === Variable shadowing === In programming languages that have non-hygienic macro systems, it is possible for existing variable bindings to be hidden from a macro by variable bindings that are created during its expansion. In [[C (programming language)|C]], this problem can be illustrated by the following fragment: <syntaxhighlight lang="c"> #define INCI(i) { int a=0; ++i; } int main(void) { int a = 4, b = 8; INCI(a); INCI(b); printf("a is now %d, b is now %d\n", a, b); return 0; }</syntaxhighlight> Running the above through the [[C preprocessor]] produces: <syntaxhighlight lang="c"> int main(void) { int a = 4, b = 8; { int a = 0; ++a; }; { int a = 0; ++b; }; printf("a is now %d, b is now %d\n", a, b); return 0; }</syntaxhighlight> The variable <code>a</code> declared in the top scope is [[Variable shadowing|shadowed]] by the <code>a</code> variable in the macro, which introduces a new [[Scope (computer science)#Lexical scoping|scope]]. As a result, <code>a</code> is never altered by the execution of the program, as the output of the compiled program shows: a is now 4, b is now 9 === Standard library function redefinition === The hygiene problem can extend beyond variable bindings. Consider this [[Common Lisp]] macro: <syntaxhighlight lang="lisp"> (defmacro my-unless (condition &body body) `(if (not ,condition) (progn ,@body))) </syntaxhighlight> While there are no references to variables in this macro, it assumes the symbols "if", "not", and "progn" are all bound to their usual definitions in the standard library. If, however the above macro is used in the following code: <syntaxhighlight lang="lisp"> (flet ((not (x) x)) (my-unless t (format t "This should not be printed!"))) </syntaxhighlight> The definition of "not" has been locally altered and so the expansion of <code>my-unless</code> changes. Note however that for Common Lisp this behavior is forbidden, as per [https://www.lispworks.com/documentation/lw70/CLHS/Body/11_abab.htm 11.1.2.1.2 Constraints on the COMMON-LISP Package for Conforming Programs]. It is also possible to completely redefine functions anyway. Some implementations of Common Lisp provide [https://www.sbcl.org/manual/#Package-Locks Package Locks] to prevent the user to change definitions in packages by mistake. === Program-defined function redefinition === Of course, the problem can occur for program-defined functions in a similar way: <syntaxhighlight lang="lisp"> (defun user-defined-operator (cond) (not cond)) (defmacro my-unless (condition &body body) `(if (user-defined-operator ,condition) (progn ,@body))) ; ... later ... (flet ((user-defined-operator (x) x)) (my-unless t (format t "This should not be printed!"))) </syntaxhighlight> The use site redefines <code>user-defined-operator</code> and hence changes the behavior of the macro.
Edit summary
(Briefly describe your changes)
By publishing changes, you agree to the
Terms of Use
, and you irrevocably agree to release your contribution under the
CC BY-SA 4.0 License
and the
GFDL
. You agree that a hyperlink or URL is sufficient attribution under the Creative Commons license.
Cancel
Editing help
(opens in new window)