emacs.d/clones/lisp/www.cliki.net/Issue DEFMACRO-VALUES.html

179 lines
13 KiB
HTML
Raw Normal View History

2022-10-07 15:47:14 +02:00
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>CLiki: Issue DEFMACRO-VALUES</title>
<link rel="alternate" type="application/atom+xml" title="ATOM feed of edits to current article"
href="https://www.cliki.net/site/feed/article.atom?title=Issue%20DEFMACRO-VALUES">
<link rel="stylesheet" href="static/css/style.css">
<link rel="stylesheet" href="static/css/colorize.css">
</head>
<body>
<span class="hidden">CLiki - Issue DEFMACRO-VALUES</span>
<div id="content"><div id="content-area"><div id="article-title">Issue DEFMACRO-VALUES</div><div id="article"><a href="Issue.html" class="category">Issue</a>: DEFMACRO-VALUES<p>Forum:<p>References: <a href="https://www.cliki.net/site/HyperSpec/Body/mac_defmacro.html" class="hyperspec">DEFMACRO</a>, <a href="https://www.cliki.net/site/HyperSpec/Body/speope_fletcm_scm_macrolet.html" class="hyperspec">MACROLET</a>, <a href="https://www.cliki.net/site/HyperSpec/Body/var_stmacroexpand-hookst.html" class="hyperspec">*MACROEXPAND-HOOK*</a>,
<a href="https://www.cliki.net/site/HyperSpec/Body/fun_macroexpa_acroexpand-1.html" class="hyperspec">MACROEXPAND-1</a>, <a href="https://www.cliki.net/site/HyperSpec/Body/acc_macro-function.html" class="hyperspec">MACRO-FUNCTION</a>, the Glossary definition for
<a href="http://www.cliki.net/site/HyperSpec/Body/glo_v.html#value">value</a>.<p>Category:<p>Edit history:
2005-09-11, Version 1 by Kalle Olavi Niemitalo<p>Status: For CLiki consideration<p><dl>
<dt>Problem Description:
</dt>
<dd>According to the description of <a href="https://www.cliki.net/site/HyperSpec/Body/mac_defmacro.html" class="hyperspec">DEFMACRO</a>,
"the value of the last <i>form</i> executed is returned as the
expansion of the macro." The glossary definition of
<a href="http://www.cliki.net/site/HyperSpec/Body/glo_v.html#value">value</a>
(1. b.) indicates that this means the primary value; any further
values are ignored. But does this truncation occur as part of the
expansion function defined by DEFMACRO, or as part of the
macroexpansion process? This matters if the user calls the expansion
function directly, or if the user's <a href="https://www.cliki.net/site/HyperSpec/Body/var_stmacroexpand-hookst.html" class="hyperspec">*MACROEXPAND-HOOK*</a> cares.<p> This also concerns <a href="https://www.cliki.net/site/HyperSpec/Body/speope_fletcm_scm_macrolet.html" class="hyperspec">MACROLET</a>, which uses "the same format used
by <a href="https://www.cliki.net/site/HyperSpec/Body/mac_defmacro.html" class="hyperspec">defmacro</a>."<p></dd>
<dt>Proposal (DEFMACRO-VALUES:PRIMARY):
</dt>
<dd>The expansion functions defined by DEFMACRO or MACROLET always return
exactly one value, even if the body attempts to return multiple values
(as the values of the last form, or by using <a href="https://www.cliki.net/site/HyperSpec/Body/speope_return-from.html" class="hyperspec">RETURN-FROM</a>).
With SETF <a href="https://www.cliki.net/site/HyperSpec/Body/acc_macro-function.html" class="hyperspec">MACRO-FUNCTION</a>, the user can specify a
macro function that returns multiple values; but only the primary value
matters when the macro function is being called by <a href="https://www.cliki.net/site/HyperSpec/Body/fun_macroexpa_acroexpand-1.html" class="hyperspec">MACROEXPAND</a>,
<a href="https://www.cliki.net/site/HyperSpec/Body/fun_macroexpa_acroexpand-1.html" class="hyperspec">MACROEXPAND-1</a>, or whatever the implementation uses to expand
macros.<p> The function that is the value of <a href="https://www.cliki.net/site/HyperSpec/Body/var_stmacroexpand-hookst.html" class="hyperspec">*MACROEXPAND-HOOK*</a> is not
required to preserve multiple values returned by the macro function,
and it might not even see all the values if another hook has
interposed itself.<p></dd>
<dt>Rationale (DEFMACRO-VALUES:PRIMARY):
</dt>
<dd>According to the description of <a href="https://www.cliki.net/site/HyperSpec/Body/mac_defmacro.html" class="hyperspec">DEFMACRO</a>,
"the expansion function returns a
<a href="http://www.cliki.net/site/HyperSpec/Body/glo_f.html#form">form</a>."
Make it behave that way.<p></dd>
<dt>Proposal (DEFMACRO-VALUES:ALL):
</dt>
<dd>The expansion functions defined by DEFMACRO or MACROLET return all the
values of the body, but only the primary value matters when the expansion
function is being called by <a href="https://www.cliki.net/site/HyperSpec/Body/fun_macroexpa_acroexpand-1.html" class="hyperspec">MACROEXPAND</a>, <a href="https://www.cliki.net/site/HyperSpec/Body/fun_macroexpa_acroexpand-1.html" class="hyperspec">MACROEXPAND-1</a>,
or whatever the implementation uses to expand macros.<p> The function that is the value of <a href="https://www.cliki.net/site/HyperSpec/Body/var_stmacroexpand-hookst.html" class="hyperspec">*MACROEXPAND-HOOK*</a> is not
required to preserve multiple values returned by the macro function,
and it might not even see all the values if another hook has
interposed itself.<p></dd>
<dt>Rationale (DEFMACRO-VALUES:ALL):
</dt>
<dd>This seems to be what the implementations do now, and is helpful if
users want to use MACROLET as a general way to add information to the
lexical environment.<p></dd>
<dt>Proposal (DEFMACRO-VALUES:EXPLICITLY-VAGUE):
</dt>
<dd>It is unspecified whether the expansion functions defined by
DEFMACRO or MACROLET return all the values of the body, or just the
primary value. With SETF <a href="https://www.cliki.net/site/HyperSpec/Body/acc_macro-function.html" class="hyperspec">MACRO-FUNCTION</a>, the user can
specify a macro function that returns multiple values. In any case,
only the primary value matters when the expansion function is being
called by <a href="https://www.cliki.net/site/HyperSpec/Body/fun_macroexpa_acroexpand-1.html" class="hyperspec">MACROEXPAND</a>, <a href="https://www.cliki.net/site/HyperSpec/Body/fun_macroexpa_acroexpand-1.html" class="hyperspec">MACROEXPAND-1</a>, or whatever
the implementation uses to expand macros.<p> The function that is the value of <a href="https://www.cliki.net/site/HyperSpec/Body/var_stmacroexpand-hookst.html" class="hyperspec">*MACROEXPAND-HOOK*</a> is not
required to preserve multiple values returned by the macro function,
and it might not even see all the values if another hook has
interposed itself.<p></dd>
<dt>Rationale (DEFMACRO-VALUES:EXPLICITLY-VAGUE):
</dt>
<dd>Clarify the spec without requiring implementations to change.<p></dd>
<dt>Proposal (DEFMACRO-VALUES:THROUGHOUT):
</dt>
<dd>The expansion functions defined by DEFMACRO and MACROLET return all the
values of the body, but only the primary value matters when the expansion
function is being called by <a href="https://www.cliki.net/site/HyperSpec/Body/fun_macroexpa_acroexpand-1.html" class="hyperspec">MACROEXPAND</a>, <a href="https://www.cliki.net/site/HyperSpec/Body/fun_macroexpa_acroexpand-1.html" class="hyperspec">MACROEXPAND-1</a>,
or whatever the implementation uses to expand macros.<p> The function that is the value of <a href="https://www.cliki.net/site/HyperSpec/Body/var_stmacroexpand-hookst.html" class="hyperspec">*MACROEXPAND-HOOK*</a> will see
all the values returned by the macro function, and must preserve
them. Because it cannot normally know how the extra values will be
used, it should pass them through unchanged.<p></dd>
<dt>Rationale (DEFMACRO-VALUES:THROUGHOUT):
</dt>
<dd>If users define macros that return multiple values, then the
implementation and user-defined hooks should propagate them as far as
possible, in case some hook somewhere knows what to do with them.
Admittedly, this is rather far-fetched: because <a href="https://www.cliki.net/site/HyperSpec/Body/fun_macroexpa_acroexpand-1.html" class="hyperspec">MACROEXPAND-1</a>
will discard the extra values anyway, users are unlikely to call it
on such macros, and then the value of <a href="https://www.cliki.net/site/HyperSpec/Body/var_stmacroexpand-hookst.html" class="hyperspec">*MACROEXPAND-HOOK*</a> won't
get called either.<p></dd>
<dt>Test case:
</dt>
<dd></dd>
</dl><pre>
(defmacro foo ()
(values 1 2 3))
(multiple-value-list (funcall (macro-function &#039;foo) &#039;(foo) nil))
;; returns (1) for DEFMACRO-VALUES:PRIMARY,
;; returns (1 2 3) for DEFMACRO-VALUES:ALL or DEFMACRO-VALUES:THROUGHOUT,
;; returns either for DEFMACRO-VALUES:EXPLICITLY-VAGUE.
(let ((*macroexpand-hook*
#&#039;(lambda (function form env)
(let ((values (multiple-value-list (funcall function form env))))
(format *trace-output* &quot;~&amp;Values:~{ ~S~}~%&quot; values)
(values-list values)))))
(macroexpand-1 &#039;(foo)))
;; outputs &quot;Values: 1&quot; for DEFMACRO-VALUES:PRIMARY,
;; outputs &quot;Values: 1 2 3&quot; for DEFMACRO-VALUES:THROUGHOUT,
;; outputs either for DEFMACRO-VALUES:ALL or DEFMACRO-VALUES:EXPLICITLY-VAGUE,
;; always returns 1 and T.
</pre><p><dt>Rationale:
</dt><dd><p></dd><dt>Current practice:
</dt><dd>
<a href="SBCL.html" class="internal">SBCL</a> 0.9.3.51, <a href="CLISP.html" class="internal">CLISP</a> 2.34, and Allegro CL 6.2 seem to
implement DEFMACRO-VALUES:ALL.<p></dd><dt>Cost to Implementors:
</dt><dd>DEFMACRO-VALUES:EXPLICITLY-VAGUE is intended not to require any
changes in implementations.<p> It seems possible that all current implementations support
DEFMACRO-VALUES:ALL, in which case that would not require changes
either. Some implementations may currently support
DEFMACRO-VALUES:PRIMARY instead. Switching from either one to the
other would require some effort, and might make macros expand a
little slower.<p> DEFMACRO-VALUES:THROUGHOUT would additionally require implementors to
examine and correct all of the functions they place in
<a href="https://www.cliki.net/site/HyperSpec/Body/var_stmacroexpand-hookst.html" class="hyperspec">*MACROEXPAND-HOOK*</a>.<p></dd><dt>Cost to Users:<p></dt><dd>DEFMACRO-VALUES:EXPLICITLY-VAGUE might make users' programs less
portable, if all current implementations support DEFMACRO-VALUES:ALL
and the programs have come to rely on that and some future implementation
chooses to behave like DEFMACRO-VALUES:PRIMARY instead.<p> If all current implementations support DEFMACRO-VALUES:ALL, then making
this official would not hurt users, but we don't know that yet.<p> Requiring DEFMACRO-VALUES:PRIMARY would break programs that haven't been
careful about portability.<p> DEFMACRO-VALUES:THROUGHOUT would additionally require users to
examine and correct all of the functions they place in
<a href="https://www.cliki.net/site/HyperSpec/Body/var_stmacroexpand-hookst.html" class="hyperspec">*MACROEXPAND-HOOK*</a>.<p></dd><dt>Cost of Non-Adoption:
</dt><dd>Unclear spec. Users don't know what they can rely on, and may
assume too much in programs intended to be portable.<p></dd><dt>Benefits:
</dt><dd><p></dd><dt>Aesthetics:
</dt><dd><p></dd><dt>Discussion:
</dt><dd><p></dd></div></div>
<div id="footer" class="buttonbar"><ul><li><a href="Issue&#32;DEFMACRO-VALUES.html">Current version</a></li>
<li><a href="https://www.cliki.net/site/history?article=Issue%20DEFMACRO-VALUES">History</a></li>
<li><a href="https://www.cliki.net/site/backlinks?article=Issue%20DEFMACRO-VALUES">Backlinks</a></li><li><a href="https://www.cliki.net/site/edit-article?title=Issue%20DEFMACRO-VALUES&amp;from-revision=3722748800">Edit</a></li><li><a href="https://www.cliki.net/site/edit-article?create=t">Create</a></li></ul></div>
</div>
<div id="header-buttons" class="buttonbar">
<ul>
<li><a href="https://www.cliki.net/">Home</a></li>
<li><a href="https://www.cliki.net/site/recent-changes">Recent Changes</a></li>
<li><a href="CLiki.html">About</a></li>
<li><a href="Text&#32;Formatting.html">Text Formatting</a></li>
<li><a href="https://www.cliki.net/site/tools">Tools</a></li>
</ul>
<div id="search">
<form action="https://www.cliki.net/site/search">
<label for="search_query" class="hidden">Search CLiki</label>
<input type="text" name="query" id="search_query" value="" />
<input type="submit" value="search" />
</form>
</div>
</div>
<div id="pageheader">
<div id="header">
<span id="logo">CLiki</span>
<span id="slogan">the common lisp wiki</span>
<div id="login"><form method="post" action="https://www.cliki.net/site/login">
<label for="login_name" class="hidden">Account name</label>
<input type="text" name="name" id="login_name" class="login_input" />
<label for= "login_password" class="hidden">Password</label>
<input type="password" name="password" id="login_password" class="login_input" />
<input type="submit" name="login" value="login" id="login_submit" /><br />
<div id="register"><a href="https://www.cliki.net/site/register">register</a></div>
<input type="submit" name="reset-pw" value="reset password" id="reset_pw" />
</form>
</div>
</div>
</div>
</body></html>