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!
==Strategies used in languages that lack hygienic macros== The hygiene problem can be resolved with conventional macros using several alternative solutions. === Obfuscation === The simplest solution, if temporary storage is needed during macro expansion, is to use unusual variables names in the macro in hope that the same names will never be used by the rest of the program. <syntaxhighlight lang="c"> #define INCI(i) { int INCIa = 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> Until a variable named <code>INCIa</code> is created, this solution produces the correct output: a is now 5, b is now 9 The problem is solved for the current program, but this solution is not robust. The variables used inside the macro and those in the rest of the program have to be kept in sync by the programmer. Specifically, using the macro <code>INCI</code> on a variable <code>INCIa</code> is going to fail in the same way that the original macro failed on a variable <code>a</code>. === <span class="anchor" id="Gensym"></span> Temporary symbol creation === In some programming languages, it is possible for a new variable name, or symbol, to be generated and bound to a temporary location. The language processing system ensures that this never clashes with another name or location in the execution environment. The responsibility for choosing to use this feature within the body of a macro definition is left to the programmer. This method was used in [[MacLisp]], where a function named <code>gensym</code> could be used to generate a new symbol name. Similar functions (usually named <code>gensym</code> as well) exist in many Lisp-like languages, including the widely implemented [[Common Lisp]] standard<ref>{{Cite web |url=http://www.lispworks.com/documentation/HyperSpec/Body/f_gensym.htm#gensym |title=CLHS: Function GENSYM}}</ref> and [[Elisp]]. Although symbol creation solves the variable shadowing issue, it does not directly solve the issue of function redefinition.<ref>{{cite web |title=hygiene-versus-gensym |url=http://community.schemewiki.org/?hygiene-versus-gensym |website=community.schemewiki.org |access-date=11 June 2022}}</ref> However, <code>gensym</code>, macro facilities, and standard library functions are sufficient to embed hygienic macros in an unhygienic language.<ref>{{cite journal |last1=Costanza |first1=Pascal |last2=D'Hondt |first2=Theo |title=Embedding Hygiene-Compatible Macros in an Unhygienic Macro System |journal=Journal of Universal Computer Science |date=2010 |volume=16 |issue=2 |pages=271β295 |doi=10.3217/jucs-016-02-0271 |doi-access=free|citeseerx=10.1.1.424.5218}}</ref> === Read-time uninterned symbol === This is similar to obfuscation in that a single name is shared by multiple expansions of the same macro. Unlike an unusual name, however, a read time uninterned symbol is used (denoted by the <code>#:</code> notation), for which it is impossible to occur outside of the macro, similar to <code>gensym</code>. === Packages === Using packages such as in Common Lisp, the macro simply uses a private symbol from the package in which the macro is defined. The symbol will not accidentally occur in user code. User code would have to reach inside the package using the double colon (<code>::</code>) notation to give itself permission to use the private symbol, for instance <code>cool-macros::secret-sym</code>. At that point, the issue of accidental lack of hygiene is moot. Furthermore the ANSI Common Lisp standard categorizes redefining standard functions and operators, globally or locally, as invoking [[undefined behavior]]. Such usage can be thus diagnosed by the implementation as erroneous. Thus the Lisp package system provide a viable, complete solution to the macro hygiene problem, which can be regarded as an instance of name clashing. For example, in the [[#Program-defined function redefinition|program-defined function redefinition example]], the <code>my-unless</code> macro can reside in its own package, where <code>user-defined-operator</code> is a private symbol in that package. The symbol <code>user-defined-operator</code> occurring in the user code will then be a different symbol, unrelated to the one used in the definition of the <code>my-unless</code> macro. === Literal objects === In some languages the expansion of a macro does not need to correspond to textual code; rather than expanding to an expression containing the symbol <code>f</code>, a macro may produce an expansion containing the actual object referred to by <code>f</code>. Similarly if the macro needs to use local variables or objects defined in the macro's package, it can expand to an invocation of a closure object whose enclosing lexical environment is that of the macro definition.
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)