summaryrefslogtreecommitdiff
path: root/devdocs/elisp/backquote-patterns.html
diff options
context:
space:
mode:
Diffstat (limited to 'devdocs/elisp/backquote-patterns.html')
-rw-r--r--devdocs/elisp/backquote-patterns.html38
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 &copy; 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>