diff options
| author | Craig Jennings <c@cjennings.net> | 2024-04-07 13:41:34 -0500 |
|---|---|---|
| committer | Craig Jennings <c@cjennings.net> | 2024-04-07 13:41:34 -0500 |
| commit | 754bbf7a25a8dda49b5d08ef0d0443bbf5af0e36 (patch) | |
| tree | f1190704f78f04a2b0b4c977d20fe96a828377f1 /devdocs/elisp/inline-functions.html | |
new repository
Diffstat (limited to 'devdocs/elisp/inline-functions.html')
| -rw-r--r-- | devdocs/elisp/inline-functions.html | 35 |
1 files changed, 35 insertions, 0 deletions
diff --git a/devdocs/elisp/inline-functions.html b/devdocs/elisp/inline-functions.html new file mode 100644 index 00000000..95709056 --- /dev/null +++ b/devdocs/elisp/inline-functions.html @@ -0,0 +1,35 @@ + <h3 class="section">Inline Functions</h3> <p>An <em>inline function</em> is a function that works just like an ordinary function, except for one thing: when you byte-compile a call to the function (see <a href="byte-compilation">Byte Compilation</a>), the function’s definition is expanded into the caller. </p> <p>The simple way to define an inline function, is to write <code>defsubst</code> instead of <code>defun</code>. The rest of the definition looks just the same, but using <code>defsubst</code> says to make it inline for byte compilation. </p> <dl> <dt id="defsubst">Macro: <strong>defsubst</strong> <em>name args [doc] [declare] [interactive] body…</em> +</dt> <dd><p>This macro defines an inline function. Its syntax is exactly the same as <code>defun</code> (see <a href="defining-functions">Defining Functions</a>). </p></dd> +</dl> <p>Making a function inline often makes its function calls run faster. But it also has disadvantages. For one thing, it reduces flexibility; if you change the definition of the function, calls already inlined still use the old definition until you recompile them. </p> <p>Another disadvantage is that making a large function inline can increase the size of compiled code both in files and in memory. Since the speed advantage of inline functions is greatest for small functions, you generally should not make large functions inline. </p> <p>Also, inline functions do not behave well with respect to debugging, tracing, and advising (see <a href="advising-functions">Advising Functions</a>). Since ease of debugging and the flexibility of redefining functions are important features of Emacs, you should not make a function inline, even if it’s small, unless its speed is really crucial, and you’ve timed the code to verify that using <code>defun</code> actually has performance problems. </p> <p>After an inline function is defined, its inline expansion can be performed later on in the same file, just like macros. </p> <p>It’s possible to use <code>defmacro</code> to define a macro to expand into the same code that an inline function would execute (see <a href="macros">Macros</a>). But the macro would be limited to direct use in expressions—a macro cannot be called with <code>apply</code>, <code>mapcar</code> and so on. Also, it takes some work to convert an ordinary function into a macro. To convert it into an inline function is easy; just replace <code>defun</code> with <code>defsubst</code>. Since each argument of an inline function is evaluated exactly once, you needn’t worry about how many times the body uses the arguments, as you do for macros. </p> <p>Alternatively, you can define a function by providing the code which will inline it as a compiler macro. The following macros make this possible. </p> <dl> <dt id="define-inline">Macro: <strong>define-inline</strong> <em>name args [doc] [declare] body…</em> +</dt> <dd> +<p>Define a function <var>name</var> by providing code that does its inlining, as a compiler macro. The function will accept the argument list <var>args</var> and will have the specified <var>body</var>. </p> <p>If present, <var>doc</var> should be the function’s documentation string (see <a href="function-documentation">Function Documentation</a>); <var>declare</var>, if present, should be a <code>declare</code> form (see <a href="declare-form">Declare Form</a>) specifying the function’s metadata. </p> +</dd> +</dl> <p>Functions defined via <code>define-inline</code> have several advantages with respect to macros defined by <code>defsubst</code> or <code>defmacro</code>: </p> <ul class="no-bullet"> <li>- They can be passed to <code>mapcar</code> (see <a href="mapping-functions">Mapping Functions</a>). </li> +<li>- They are more efficient. </li> +<li>- They can be used as <em>place forms</em> to store values (see <a href="generalized-variables">Generalized Variables</a>). </li> +<li>- They behave in a more predictable way than <code>cl-defsubst</code> (see <a href="https://www.gnu.org/software/emacs/manual/html_node/cl/Argument-Lists.html#Argument-Lists">Argument Lists</a> in <cite>Common Lisp Extensions for GNU Emacs Lisp</cite>). </li> +</ul> <p>Like <code>defmacro</code>, a function inlined with <code>define-inline</code> inherits the scoping rules, either dynamic or lexical, from the call site. See <a href="variable-scoping">Variable Scoping</a>. </p> <p>The following macros should be used in the body of a function defined by <code>define-inline</code>. </p> <dl> <dt id="inline-quote">Macro: <strong>inline-quote</strong> <em>expression</em> +</dt> <dd><p>Quote <var>expression</var> for <code>define-inline</code>. This is similar to the backquote (see <a href="backquote">Backquote</a>), but quotes code and accepts only <code>,</code>, not <code>,@</code>. </p></dd> +</dl> <dl> <dt id="inline-letevals">Macro: <strong>inline-letevals</strong> <em>(bindings…) body…</em> +</dt> <dd> +<p>This provides a convenient way to ensure that the arguments to an inlined function are evaluated exactly once, as well as to create local variables. </p> <p>It’s similar to <code>let</code> (see <a href="local-variables">Local Variables</a>): It sets up local variables as specified by <var>bindings</var>, and then evaluates <var>body</var> with those bindings in effect. </p> <p>Each element of <var>bindings</var> should be either a symbol or a list of the form <code>(<var>var</var> <var>expr</var>)</code>; the result is to evaluate <var>expr</var> and bind <var>var</var> to the result. However, when an element of <var>bindings</var> is just a symbol <var>var</var>, the result of evaluating <var>var</var> is re-bound to <var>var</var> (which is quite different from the way <code>let</code> works). </p> <p>The tail of <var>bindings</var> can be either <code>nil</code> or a symbol which should hold a list of arguments, in which case each argument is evaluated, and the symbol is bound to the resulting list. </p> +</dd> +</dl> <dl> <dt id="inline-const-p">Macro: <strong>inline-const-p</strong> <em>expression</em> +</dt> <dd><p>Return non-<code>nil</code> if the value of <var>expression</var> is already known. </p></dd> +</dl> <dl> <dt id="inline-const-val">Macro: <strong>inline-const-val</strong> <em>expression</em> +</dt> <dd><p>Return the value of <var>expression</var>. </p></dd> +</dl> <dl> <dt id="inline-error">Macro: <strong>inline-error</strong> <em>format &rest args</em> +</dt> <dd><p>Signal an error, formatting <var>args</var> according to <var>format</var>. </p></dd> +</dl> <p>Here’s an example of using <code>define-inline</code>: </p> <div class="lisp"> <pre class="lisp">(define-inline myaccessor (obj) + (inline-letevals (obj) + (inline-quote (if (foo-p ,obj) (aref (cdr ,obj) 3) (aref ,obj 2))))) +</pre> +</div> <p>This is equivalent to </p> <div class="lisp"> <pre class="lisp">(defsubst myaccessor (obj) + (if (foo-p obj) (aref (cdr obj) 3) (aref obj 2))) +</pre> +</div><div class="_attribution"> + <p class="_attribution-p"> + Copyright © 1990-1996, 1998-2022 Free Software Foundation, Inc. <br>Licensed under the GNU GPL license.<br> + <a href="https://www.gnu.org/software/emacs/manual/html_node/elisp/Inline-Functions.html" class="_attribution-link">https://www.gnu.org/software/emacs/manual/html_node/elisp/Inline-Functions.html</a> + </p> +</div> |
