168 lines
7.5 KiB
HTML
168 lines
7.5 KiB
HTML
|
<!DOCTYPE html>
|
||
|
<html>
|
||
|
<!-- Created by GNU Texinfo 7.1, https://www.gnu.org/software/texinfo/ -->
|
||
|
<head>
|
||
|
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
|
||
|
<!-- This manual documents Guile version 3.0.10.
|
||
|
|
||
|
Copyright (C) 1996-1997, 2000-2005, 2009-2023 Free Software Foundation,
|
||
|
Inc.
|
||
|
|
||
|
Copyright (C) 2021 Maxime Devos
|
||
|
|
||
|
Copyright (C) 2024 Tomas Volf
|
||
|
|
||
|
|
||
|
Permission is granted to copy, distribute and/or modify this document
|
||
|
under the terms of the GNU Free Documentation License, Version 1.3 or
|
||
|
any later version published by the Free Software Foundation; with no
|
||
|
Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts. A
|
||
|
copy of the license is included in the section entitled "GNU Free
|
||
|
Documentation License." -->
|
||
|
<title>Hygiene and the Top-Level (Guile Reference Manual)</title>
|
||
|
|
||
|
<meta name="description" content="Hygiene and the Top-Level (Guile Reference Manual)">
|
||
|
<meta name="keywords" content="Hygiene and the Top-Level (Guile Reference Manual)">
|
||
|
<meta name="resource-type" content="document">
|
||
|
<meta name="distribution" content="global">
|
||
|
<meta name="Generator" content=".texi2any-real">
|
||
|
<meta name="viewport" content="width=device-width,initial-scale=1">
|
||
|
|
||
|
<link href="index.html" rel="start" title="Top">
|
||
|
<link href="Concept-Index.html" rel="index" title="Concept Index">
|
||
|
<link href="index.html#SEC_Contents" rel="contents" title="Table of Contents">
|
||
|
<link href="Macros.html" rel="up" title="Macros">
|
||
|
<link href="Internal-Macros.html" rel="next" title="Internal Macros">
|
||
|
<link href="Macro-Expansion.html" rel="prev" title="Macro Expansion">
|
||
|
<style type="text/css">
|
||
|
<!--
|
||
|
a.copiable-link {visibility: hidden; text-decoration: none; line-height: 0em}
|
||
|
div.example {margin-left: 3.2em}
|
||
|
span:hover a.copiable-link {visibility: visible}
|
||
|
-->
|
||
|
</style>
|
||
|
<link rel="stylesheet" type="text/css" href="https://www.gnu.org/software/gnulib/manual.css">
|
||
|
|
||
|
|
||
|
</head>
|
||
|
|
||
|
<body lang="en">
|
||
|
<div class="subsection-level-extent" id="Hygiene-and-the-Top_002dLevel">
|
||
|
<div class="nav-panel">
|
||
|
<p>
|
||
|
Next: <a href="Internal-Macros.html" accesskey="n" rel="next">Internal Macros</a>, Previous: <a href="Macro-Expansion.html" accesskey="p" rel="prev">Macro Expansion</a>, Up: <a href="Macros.html" accesskey="u" rel="up">Macros</a> [<a href="index.html#SEC_Contents" title="Table of contents" rel="contents">Contents</a>][<a href="Concept-Index.html" title="Index" rel="index">Index</a>]</p>
|
||
|
</div>
|
||
|
<hr>
|
||
|
<h4 class="subsection" id="Hygiene-and-the-Top_002dLevel-1"><span>6.8.10 Hygiene and the Top-Level<a class="copiable-link" href="#Hygiene-and-the-Top_002dLevel-1"> ¶</a></span></h4>
|
||
|
|
||
|
<p>Consider the following macro.
|
||
|
</p>
|
||
|
<div class="example lisp">
|
||
|
<pre class="lisp-preformatted">(define-syntax-rule (defconst name val)
|
||
|
(begin
|
||
|
(define t val)
|
||
|
(define-syntax-rule (name) t)))
|
||
|
</pre></div>
|
||
|
|
||
|
<p>If we use it to make a couple of bindings:
|
||
|
</p>
|
||
|
<div class="example lisp">
|
||
|
<pre class="lisp-preformatted">(defconst foo 42)
|
||
|
(defconst bar 37)
|
||
|
</pre></div>
|
||
|
|
||
|
<p>The expansion would look something like this:
|
||
|
</p>
|
||
|
<div class="example lisp">
|
||
|
<pre class="lisp-preformatted">(begin
|
||
|
(define t 42)
|
||
|
(define-syntax-rule (foo) t))
|
||
|
(begin
|
||
|
(define t 37)
|
||
|
(define-syntax-rule (bar) t))
|
||
|
</pre></div>
|
||
|
|
||
|
<p>As the two <code class="code">t</code> bindings were introduced by the macro, they should
|
||
|
be introduced hygienically – and indeed they are, inside a lexical
|
||
|
contour (a <code class="code">let</code> or some other lexical scope). The <code class="code">t</code>
|
||
|
reference in <code class="code">foo</code> is distinct to the reference in <code class="code">bar</code>.
|
||
|
</p>
|
||
|
<p>At the top-level things are more complicated. Before Guile 2.2, a use
|
||
|
of <code class="code">defconst</code> at the top-level would not introduce a fresh binding
|
||
|
for <code class="code">t</code>. This was consistent with a weaselly interpretation of the
|
||
|
Scheme standard, in which all possible bindings may be assumed to exist,
|
||
|
at the top-level, and in which we merely take advantage of toplevel
|
||
|
<code class="code">define</code> of an existing binding being equivalent to <code class="code">set!</code>.
|
||
|
But it’s not a good reason.
|
||
|
</p>
|
||
|
<p>The solution is to create fresh names for all bindings introduced by
|
||
|
macros – not just bindings in lexical contours, but also bindings
|
||
|
introduced at the top-level.
|
||
|
</p>
|
||
|
<p>However, the obvious strategy of just giving random names to introduced
|
||
|
toplevel identifiers poses a problem for separate compilation. Consider
|
||
|
without loss of generality a <code class="code">defconst</code> of <code class="code">foo</code> in module
|
||
|
<code class="code">a</code> that introduces the fresh top-level name <code class="code">t-1</code>. If we
|
||
|
then compile a module <code class="code">b</code> that uses <code class="code">foo</code>, there is now a
|
||
|
reference to <code class="code">t-1</code> in module <code class="code">b</code>. If module <code class="code">a</code> is then
|
||
|
expanded again, for whatever reason, for example in a simple
|
||
|
recompilation, the introduced <code class="code">t</code> gets a fresh name; say,
|
||
|
<code class="code">t-2</code>. Now module <code class="code">b</code> has broken because module <code class="code">a</code> no
|
||
|
longer has a binding for <code class="code">t-1</code>.
|
||
|
</p>
|
||
|
<p>If introduced top-level identifiers “escape” a module, in whatever
|
||
|
way, they then form part of the binary interface (ABI) of a module. It
|
||
|
is unacceptable from an engineering point of view to allow the ABI to
|
||
|
change randomly. (It also poses practical problems in meeting the
|
||
|
recompilation conditions of the Lesser GPL license, for such modules.)
|
||
|
For this reason many people prefer to never use identifier-introducing
|
||
|
macros at the top-level, instead making those macros receive the names
|
||
|
for their introduced identifiers as part of their arguments, or to
|
||
|
construct them programmatically and use <code class="code">datum->syntax</code>. But this
|
||
|
approach requires omniscience as to the implementation of all macros one
|
||
|
might use, and also limits the expressive power of Scheme macros.
|
||
|
</p>
|
||
|
<p>There is no perfect solution to this issue. Guile does a terrible thing
|
||
|
here. When it goes to introduce a top-level identifier, Guile gives the
|
||
|
identifier a pseudo-fresh name: a name that depends on the hash of the
|
||
|
source expression in which the name occurs. The result in this case is
|
||
|
that the introduced definitions expand as:
|
||
|
</p>
|
||
|
<div class="example lisp">
|
||
|
<pre class="lisp-preformatted">(begin
|
||
|
(define t-1dc5e42de7c1050c 42)
|
||
|
(define-syntax-rule (foo) t-1dc5e42de7c1050c))
|
||
|
(begin
|
||
|
(define t-10cb8ce9fdddd6e9 37)
|
||
|
(define-syntax-rule (bar) t-10cb8ce9fdddd6e9))
|
||
|
</pre></div>
|
||
|
|
||
|
<p>However, note that as the hash depends solely on the expression
|
||
|
introducing the definition, we also have:
|
||
|
</p>
|
||
|
<div class="example lisp">
|
||
|
<pre class="lisp-preformatted">(defconst baz 42)
|
||
|
⇒ (begin
|
||
|
(define t-1dc5e42de7c1050c 42)
|
||
|
(define-syntax-rule (baz) t-1dc5e42de7c1050c))
|
||
|
</pre></div>
|
||
|
|
||
|
<p>Note that the introduced binding has the same name! This is because the
|
||
|
source expression, <code class="code">(define t 42)</code>, was the same. Probably you
|
||
|
will never see an error in this area, but it is important to understand
|
||
|
the components of the interface of a module, and that interface may
|
||
|
include macro-introduced identifiers.
|
||
|
</p>
|
||
|
|
||
|
</div>
|
||
|
<hr>
|
||
|
<div class="nav-panel">
|
||
|
<p>
|
||
|
Next: <a href="Internal-Macros.html">Internal Macros</a>, Previous: <a href="Macro-Expansion.html">Macro Expansion</a>, Up: <a href="Macros.html">Macros</a> [<a href="index.html#SEC_Contents" title="Table of contents" rel="contents">Contents</a>][<a href="Concept-Index.html" title="Index" rel="index">Index</a>]</p>
|
||
|
</div>
|
||
|
|
||
|
|
||
|
|
||
|
</body>
|
||
|
</html>
|