1
0
Fork 0
cl-sites/guile.html_node/Hygiene-and-the-Top_002dLevel.html
2024-12-17 12:49:28 +01:00

167 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> &nbsp; [<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"> &para;</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 &ndash; 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&rsquo;s not a good reason.
</p>
<p>The solution is to create fresh names for all bindings introduced by
macros &ndash; 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 &ldquo;escape&rdquo; 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-&gt;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)
&rArr; (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> &nbsp; [<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>