diff options
Diffstat (limited to 'devdocs/elisp/backquote-patterns.html')
| -rw-r--r-- | devdocs/elisp/backquote-patterns.html | 38 |
1 files changed, 38 insertions, 0 deletions
diff --git a/devdocs/elisp/backquote-patterns.html b/devdocs/elisp/backquote-patterns.html new file mode 100644 index 00000000..f2d5166e --- /dev/null +++ b/devdocs/elisp/backquote-patterns.html @@ -0,0 +1,38 @@ + <h4 class="subsection">Backquote-Style Patterns</h4> <p>This subsection describes <em>backquote-style patterns</em>, a set of builtin patterns that eases structural matching. For background, see <a href="pattern_002dmatching-conditional">Pattern-Matching Conditional</a>. </p> <p>Backquote-style patterns are a powerful set of <code>pcase</code> pattern extensions (created using <code>pcase-defmacro</code>) that make it easy to match <var>expval</var> against specifications of its <em>structure</em>. </p> <p>For example, to match <var>expval</var> that must be a list of two elements whose first element is a specific string and the second element is any value, you can write a core pattern: </p> <div class="example"> <pre class="example">(and (pred listp) + ls +</pre> +<pre class="example"> (guard (= 2 (length ls))) + (guard (string= "first" (car ls))) + (let second-elem (cadr ls))) +</pre> +</div> <p>or you can write the equivalent backquote-style pattern: </p> <div class="example"> <pre class="example">`("first" ,second-elem) +</pre> +</div> <p>The backquote-style pattern is more concise, resembles the structure of <var>expval</var>, and avoids binding <code>ls</code>. </p> <p>A backquote-style pattern has the form <code>`<var>qpat</var></code> where <var>qpat</var> can have the following forms: </p> <dl compact> <dt><code>(<var>qpat1</var> . <var>qpat2</var>)</code></dt> <dd> +<p>Matches if <var>expval</var> is a cons cell whose <code>car</code> matches <var>qpat1</var> and whose <code>cdr</code> matches <var>qpat2</var>. This readily generalizes to lists as in <code>(<var>qpat1</var> <var>qpat2</var> …)</code>. </p> </dd> <dt><code>[<var>qpat1</var> <var>qpat2</var> … <var>qpatm</var>]</code></dt> <dd> +<p>Matches if <var>expval</var> is a vector of length <var>m</var> whose <code>0</code>..<code>(<var>m</var>-1)</code>th elements match <var>qpat1</var>, <var>qpat2</var> … <var>qpatm</var>, respectively. </p> </dd> <dt><code><var>symbol</var></code></dt> <dt><code><var>keyword</var></code></dt> <dt><code><var>number</var></code></dt> <dt><code><var>string</var></code></dt> <dd> +<p>Matches if the corresponding element of <var>expval</var> is <code>equal</code> to the specified literal object. </p> </dd> <dt><code>,<var>pattern</var></code></dt> <dd><p>Matches if the corresponding element of <var>expval</var> matches <var>pattern</var>. Note that <var>pattern</var> is any kind that <code>pcase</code> supports. (In the example above, <code>second-elem</code> is a <var>symbol</var> core pattern; it therefore matches anything, and let-binds <code>second-elem</code>.) </p></dd> </dl> <p>The <em>corresponding element</em> is the portion of <var>expval</var> that is in the same structural position as the structural position of <var>qpat</var> in the backquote-style pattern. (In the example above, the corresponding element of <code>second-elem</code> is the second element of <var>expval</var>.) </p> <p>Here is an example of using <code>pcase</code> to implement a simple interpreter for a little expression language (note that this requires lexical binding for the lambda expression in the <code>fn</code> clause to properly capture <code>body</code> and <code>arg</code> (see <a href="lexical-binding">Lexical Binding</a>): </p> <div class="example"> <pre class="example">(defun evaluate (form env) + (pcase form + (`(add ,x ,y) (+ (evaluate x env) + (evaluate y env))) +</pre> +<pre class="example"> (`(call ,fun ,arg) (funcall (evaluate fun env) + (evaluate arg env))) + (`(fn ,arg ,body) (lambda (val) + (evaluate body (cons (cons arg val) + env)))) +</pre> +<pre class="example"> ((pred numberp) form) + ((pred symbolp) (cdr (assq form env))) + (_ (error "Syntax error: %S" form)))) +</pre> +</div> <p>The first three clauses use backquote-style patterns. <code>`(add ,x ,y)</code> is a pattern that checks that <code>form</code> is a three-element list starting with the literal symbol <code>add</code>, then extracts the second and third elements and binds them to symbols <code>x</code> and <code>y</code>, respectively. The clause body evaluates <code>x</code> and <code>y</code> and adds the results. Similarly, the <code>call</code> clause implements a function call, and the <code>fn</code> clause implements an anonymous function definition. </p> <p>The remaining clauses use core patterns. <code>(pred numberp)</code> matches if <code>form</code> is a number. On match, the body evaluates it. <code>(pred symbolp)</code> matches if <code>form</code> is a symbol. On match, the body looks up the symbol in <code>env</code> and returns its association. Finally, <code>_</code> is the catch-all pattern that matches anything, so it’s suitable for reporting syntax errors. </p> <p>Here are some sample programs in this small language, including their evaluation results: </p> <div class="example"> <pre class="example">(evaluate '(add 1 2) nil) ⇒ 3 +(evaluate '(add x y) '((x . 1) (y . 2))) ⇒ 3 +(evaluate '(call (fn x (add 1 x)) 2) nil) ⇒ 3 +(evaluate '(sub 1 2) nil) ⇒ error +</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/Backquote-Patterns.html" class="_attribution-link">https://www.gnu.org/software/emacs/manual/html_node/elisp/Backquote-Patterns.html</a> + </p> +</div> |
