summaryrefslogtreecommitdiff
path: root/devdocs/elisp/pcase-macro.html
diff options
context:
space:
mode:
Diffstat (limited to 'devdocs/elisp/pcase-macro.html')
-rw-r--r--devdocs/elisp/pcase-macro.html161
1 files changed, 161 insertions, 0 deletions
diff --git a/devdocs/elisp/pcase-macro.html b/devdocs/elisp/pcase-macro.html
new file mode 100644
index 00000000..431c65cb
--- /dev/null
+++ b/devdocs/elisp/pcase-macro.html
@@ -0,0 +1,161 @@
+ <h4 class="subsection">The pcase macro</h4> <p>For background, See <a href="pattern_002dmatching-conditional">Pattern-Matching Conditional</a>. </p> <dl> <dt id="pcase">Macro: <strong>pcase</strong> <em>expression &amp;rest clauses</em>
+</dt> <dd>
+<p>Each clause in <var>clauses</var> has the form: <code>(<var>pattern</var> <var><span class="nolinebreak">body-forms</span></var>…)</code>. </p> <p>Evaluate <var>expression</var> to determine its value, <var>expval</var>. Find the first clause in <var>clauses</var> whose <var>pattern</var> matches <var>expval</var> and pass control to that clause’s <var>body-forms</var>. </p> <p>If there is a match, the value of <code>pcase</code> is the value of the last of <var>body-forms</var> in the successful clause. Otherwise, <code>pcase</code> evaluates to <code>nil</code>. </p>
+</dd>
+</dl> <p>Each <var>pattern</var> has to be a <em>pcase pattern</em>, which can use either one of the core patterns defined below, or one of the patterns defined via <code>pcase-defmacro</code> (see <a href="extending-pcase">Extending pcase</a>). </p> <p>The rest of this subsection describes different forms of core patterns, presents some examples, and concludes with important caveats on using the let-binding facility provided by some pattern forms. A core pattern can have the following forms: </p> <dl compact> <dt><code>_<span class="roman"> (underscore)</span></code></dt> <dd>
+<p>Matches any <var>expval</var>. This is also known as <em>don’t care</em> or <em>wildcard</em>. </p> </dd> <dt><code>'<var>val</var></code></dt> <dd>
+<p>Matches if <var>expval</var> equals <var>val</var>. The comparison is done as if by <code>equal</code> (see <a href="equality-predicates">Equality Predicates</a>). </p> </dd> <dt><code><var>keyword</var></code></dt> <dt><code><var>integer</var></code></dt> <dt><code><var>string</var></code></dt> <dd>
+<p>Matches if <var>expval</var> equals the literal object. This is a special case of <code>'<var>val</var></code>, above, possible because literal objects of these types are self-quoting. </p> </dd> <dt><code><var>symbol</var></code></dt> <dd>
+<p>Matches any <var>expval</var>, and additionally let-binds <var>symbol</var> to <var>expval</var>, such that this binding is available to <var>body-forms</var> (see <a href="dynamic-binding">Dynamic Binding</a>). </p> <p>If <var>symbol</var> is part of a sequencing pattern <var>seqpat</var> (e.g., by using <code>and</code>, below), the binding is also available to the portion of <var>seqpat</var> following the appearance of <var>symbol</var>. This usage has some caveats, see <a href="#pcase_002dsymbol_002dcaveats">caveats</a>. </p> <p>Two symbols to avoid are <code>t</code>, which behaves like <code>_</code> (above) and is deprecated, and <code>nil</code>, which signals an error. Likewise, it makes no sense to bind keyword symbols (see <a href="constant-variables">Constant Variables</a>). </p> </dd> <dt><code>(cl-type <var>type</var>)</code></dt> <dd>
+<p>Matches if <var>expval</var> is of type <var>type</var>, which is a type descriptor as accepted by <code>cl-typep</code> (see <a href="https://www.gnu.org/software/emacs/manual/html_node/cl/Type-Predicates.html#Type-Predicates">Type Predicates</a> in <cite>Common Lisp Extensions</cite>). Examples: </p> <div class="lisp"> <pre class="lisp">(cl-type integer)
+(cl-type (integer 0 10))
+</pre>
+</div> </dd> <dt><code>(pred <var>function</var>)</code></dt> <dd>
+<p>Matches if the predicate <var>function</var> returns non-<code>nil</code> when called on <var>expval</var>. The test can be negated with the syntax <code>(pred (not <var>function</var>))</code>. The predicate <var>function</var> can have one of the following forms: </p> <dl compact> <dt>function name (a symbol)</dt> <dd>
+<p>Call the named function with one argument, <var>expval</var>. </p> <p>Example: <code>integerp</code> </p> </dd> <dt>lambda expression</dt> <dd>
+<p>Call the anonymous function with one argument, <var>expval</var> (see <a href="lambda-expressions">Lambda Expressions</a>). </p> <p>Example: <code>(lambda (n) (= 42 n))</code> </p> </dd> <dt>function call with <var>n</var> args</dt> <dd>
+<p>Call the function (the first element of the function call) with <var>n</var> arguments (the other elements) and an additional <var>n</var>+1-th argument that is <var>expval</var>. </p> <p>Example: <code>(= 42)</code> In this example, the function is <code>=</code>, <var>n</var> is one, and the actual function call becomes: <code>(= 42 <var>expval</var>)</code>. </p>
+</dd> </dl> </dd> <dt><code>(app <var>function</var> <var>pattern</var>)</code></dt> <dd>
+<p>Matches if <var>function</var> called on <var>expval</var> returns a value that matches <var>pattern</var>. <var>function</var> can take one of the forms described for <code>pred</code>, above. Unlike <code>pred</code>, however, <code>app</code> tests the result against <var>pattern</var>, rather than against a boolean truth value. </p> </dd> <dt><code>(guard <var>boolean-expression</var>)</code></dt> <dd>
+<p>Matches if <var>boolean-expression</var> evaluates to non-<code>nil</code>. </p> </dd> <dt><code>(let <var>pattern</var> <var>expr</var>)</code></dt> <dd><p>Evaluates <var>expr</var> to get <var>exprval</var> and matches if <var>exprval</var> matches <var>pattern</var>. (It is called <code>let</code> because <var>pattern</var> can bind symbols to values using <var>symbol</var>.) </p></dd> </dl> <p>A <em>sequencing pattern</em> (also known as <var>seqpat</var>) is a pattern that processes its sub-pattern arguments in sequence. There are two for <code>pcase</code>: <code>and</code> and <code>or</code>. They behave in a similar manner to the special forms that share their name (see <a href="combining-conditions">Combining Conditions</a>), but instead of processing values, they process sub-patterns. </p> <dl compact> <dt><code>(and <var>pattern1</var>…)</code></dt> <dd>
+<p>Attempts to match <var>pattern1</var>…, in order, until one of them fails to match. In that case, <code>and</code> likewise fails to match, and the rest of the sub-patterns are not tested. If all sub-patterns match, <code>and</code> matches. </p> </dd> <dt><code>(or <var>pattern1</var> <var>pattern2</var>…)</code></dt> <dd>
+<p>Attempts to match <var>pattern1</var>, <var>pattern2</var>, …, in order, until one of them succeeds. In that case, <code>or</code> likewise matches, and the rest of the sub-patterns are not tested. </p> <p>To present a consistent environment (see <a href="intro-eval">Intro Eval</a>) to <var>body-forms</var> (thus avoiding an evaluation error on match), the set of variables bound by the pattern is the union of the variables bound by each sub-pattern. If a variable is not bound by the sub-pattern that matched, then it is bound to <code>nil</code>. </p>
+</dd> <dt><code>(rx <var>rx-expr</var>…)</code></dt> <dd>
+<p>Matches strings against the regexp <var>rx-expr</var>…, using the <code>rx</code> regexp notation (see <a href="rx-notation">Rx Notation</a>), as if by <code>string-match</code>. </p> <p>In addition to the usual <code>rx</code> syntax, <var>rx-expr</var>… can contain the following constructs: </p> <dl compact> <dt><code>(let <var>ref</var> <var>rx-expr</var>…)</code></dt> <dd>
+<p>Bind the symbol <var>ref</var> to a submatch that matches <var>rx-expr</var><small class="enddots">...</small>. <var>ref</var> is bound in <var>body-forms</var> to the string of the submatch or nil, but can also be used in <code>backref</code>. </p> </dd> <dt><code>(backref <var>ref</var>)</code></dt> <dd><p>Like the standard <code>backref</code> construct, but <var>ref</var> can here also be a name introduced by a previous <code>(let <var>ref</var> …)</code> construct. </p></dd> </dl> </dd> </dl> <h4 class="subheading">Example: Advantage Over <code>cl-case</code>
+</h4> <p>Here’s an example that highlights some advantages <code>pcase</code> has over <code>cl-case</code> (see <a href="https://www.gnu.org/software/emacs/manual/html_node/cl/Conditionals.html#Conditionals">Conditionals</a> in <cite>Common Lisp Extensions</cite>). </p> <div class="example"> <pre class="example">(pcase (get-return-code x)
+ ;; string
+ ((and (pred stringp) msg)
+ (message "%s" msg))
+</pre>
+<pre class="example"> ;; symbol
+ ('success (message "Done!"))
+ ('would-block (message "Sorry, can't do it now"))
+ ('read-only (message "The shmliblick is read-only"))
+ ('access-denied (message "You do not have the needed rights"))
+</pre>
+<pre class="example"> ;; default
+ (code (message "Unknown return code %S" code)))
+</pre>
+</div> <p>With <code>cl-case</code>, you would need to explicitly declare a local variable <code>code</code> to hold the return value of <code>get-return-code</code>. Also <code>cl-case</code> is difficult to use with strings because it uses <code>eql</code> for comparison. </p> <h4 class="subheading">Example: Using <code>and</code>
+</h4> <p>A common idiom is to write a pattern starting with <code>and</code>, with one or more <var>symbol</var> sub-patterns providing bindings to the sub-patterns that follow (as well as to the body forms). For example, the following pattern matches single-digit integers. </p> <div class="example"> <pre class="example">(and
+ (pred integerp)
+ n ; <span class="roman">bind <code>n</code> to <var>expval</var></span>
+ (guard (&lt;= -9 n 9)))
+</pre>
+</div> <p>First, <code>pred</code> matches if <code>(integerp <var>expval</var>)</code> evaluates to non-<code>nil</code>. Next, <code>n</code> is a <var>symbol</var> pattern that matches anything and binds <code>n</code> to <var>expval</var>. Lastly, <code>guard</code> matches if the boolean expression <code>(&lt;= <span class="nolinebreak">-9</span> n 9)</code> (note the reference to <code>n</code>) evaluates to non-<code>nil</code>. If all these sub-patterns match, <code>and</code> matches. </p> <h4 class="subheading">Example: Reformulation with <code>pcase</code>
+</h4> <p>Here is another example that shows how to reformulate a simple matching task from its traditional implementation (function <code>grok/traditional</code>) to one using <code>pcase</code> (function <code>grok/pcase</code>). The docstring for both these functions is: “If OBJ is a string of the form "key:NUMBER", return NUMBER (a string). Otherwise, return the list ("149" default).” First, the traditional implementation (see <a href="regular-expressions">Regular Expressions</a>): </p> <div class="example"> <pre class="example">(defun grok/traditional (obj)
+ (if (and (stringp obj)
+ (string-match "^key:\\([[:digit:]]+\\)$" obj))
+ (match-string 1 obj)
+ (list "149" 'default)))
+</pre>
+
+<pre class="example">(grok/traditional "key:0") ⇒ "0"
+(grok/traditional "key:149") ⇒ "149"
+(grok/traditional 'monolith) ⇒ ("149" default)
+</pre>
+</div> <p>The reformulation demonstrates <var>symbol</var> binding as well as <code>or</code>, <code>and</code>, <code>pred</code>, <code>app</code> and <code>let</code>. </p> <div class="example"> <pre class="example">(defun grok/pcase (obj)
+ (pcase obj
+ ((or ; <span class="roman">line 1</span>
+ (and ; <span class="roman">line 2</span>
+ (pred stringp) ; <span class="roman">line 3</span>
+ (pred (string-match ; <span class="roman">line 4</span>
+ "^key:\\([[:digit:]]+\\)$")) ; <span class="roman">line 5</span>
+ (app (match-string 1) ; <span class="roman">line 6</span>
+ val)) ; <span class="roman">line 7</span>
+ (let val (list "149" 'default))) ; <span class="roman">line 8</span>
+ val))) ; <span class="roman">line 9</span>
+</pre>
+
+<pre class="example">(grok/pcase "key:0") ⇒ "0"
+(grok/pcase "key:149") ⇒ "149"
+(grok/pcase 'monolith) ⇒ ("149" default)
+</pre>
+</div> <p>The bulk of <code>grok/pcase</code> is a single clause of a <code>pcase</code> form, the pattern on lines 1-8, the (single) body form on line 9. The pattern is <code>or</code>, which tries to match in turn its argument sub-patterns, first <code>and</code> (lines 2-7), then <code>let</code> (line 8), until one of them succeeds. </p> <p>As in the previous example (see <a href="#pcase_002dexample_002d1">Example 1</a>), <code>and</code> begins with a <code>pred</code> sub-pattern to ensure the following sub-patterns work with an object of the correct type (string, in this case). If <code>(stringp <var>expval</var>)</code> returns <code>nil</code>, <code>pred</code> fails, and thus <code>and</code> fails, too. </p> <p>The next <code>pred</code> (lines 4-5) evaluates <code><span class="nolinebreak">(string-match</span> RX <var>expval</var>)</code> and matches if the result is non-<code>nil</code>, which means that <var>expval</var> has the desired form: <code>key:NUMBER</code>. Again, failing this, <code>pred</code> fails and <code>and</code>, too. </p> <p>Lastly (in this series of <code>and</code> sub-patterns), <code>app</code> evaluates <code><span class="nolinebreak">(match-string</span> 1 <var>expval</var>)</code> (line 6) to get a temporary value <var>tmp</var> (i.e., the “NUMBER” substring) and tries to match <var>tmp</var> against pattern <code>val</code> (line 7). Since that is a <var>symbol</var> pattern, it matches unconditionally and additionally binds <code>val</code> to <var>tmp</var>. </p> <p>Now that <code>app</code> has matched, all <code>and</code> sub-patterns have matched, and so <code>and</code> matches. Likewise, once <code>and</code> has matched, <code>or</code> matches and does not proceed to try sub-pattern <code>let</code> (line 8). </p> <p>Let’s consider the situation where <code>obj</code> is not a string, or it is a string but has the wrong form. In this case, one of the <code>pred</code> (lines 3-5) fails to match, thus <code>and</code> (line 2) fails to match, thus <code>or</code> (line 1) proceeds to try sub-pattern <code>let</code> (line 8). </p> <p>First, <code>let</code> evaluates <code>(list "149" 'default)</code> to get <code>("149" default)</code>, the <var>exprval</var>, and then tries to match <var>exprval</var> against pattern <code>val</code>. Since that is a <var>symbol</var> pattern, it matches unconditionally and additionally binds <code>val</code> to <var>exprval</var>. Now that <code>let</code> has matched, <code>or</code> matches. </p> <p>Note how both <code>and</code> and <code>let</code> sub-patterns finish in the same way: by trying (always successfully) to match against the <var>symbol</var> pattern <code>val</code>, in the process binding <code>val</code>. Thus, <code>or</code> always matches and control always passes to the body form (line 9). Because that is the last body form in a successfully matched <code>pcase</code> clause, it is the value of <code>pcase</code> and likewise the return value of <code>grok/pcase</code> (see <a href="what-is-a-function">What Is a Function</a>). </p> <h4 class="subheading">Caveats for <var>symbol</var> in Sequencing Patterns</h4> <p>The preceding examples all use sequencing patterns which include the <var>symbol</var> sub-pattern in some way. Here are some important details about that usage. </p> <ol> <li> When <var>symbol</var> occurs more than once in <var>seqpat</var>, the second and subsequent occurrences do not expand to re-binding, but instead expand to an equality test using <code>eq</code>. <p>The following example features a <code>pcase</code> form with two clauses and two <var>seqpat</var>, A and B. Both A and B first check that <var>expval</var> is a pair (using <code>pred</code>), and then bind symbols to the <code>car</code> and <code>cdr</code> of <var>expval</var> (using one <code>app</code> each). </p> <p>For A, because symbol <code>st</code> is mentioned twice, the second mention becomes an equality test using <code>eq</code>. On the other hand, B uses two separate symbols, <code>s1</code> and <code>s2</code>, both of which become independent bindings. </p> <div class="example"> <pre class="example">(defun grok (object)
+ (pcase object
+ ((and (pred consp) ; seqpat A
+ (app car st) ; first mention: st
+ (app cdr st)) ; second mention: st
+ (list 'eq st))
+</pre>
+<pre class="example"> ((and (pred consp) ; seqpat B
+ (app car s1) ; first mention: s1
+ (app cdr s2)) ; first mention: s2
+ (list 'not-eq s1 s2))))
+</pre>
+
+<pre class="example">(let ((s "yow!"))
+ (grok (cons s s))) ⇒ (eq "yow!")
+(grok (cons "yo!" "yo!")) ⇒ (not-eq "yo!" "yo!")
+(grok '(4 2)) ⇒ (not-eq 4 (2))
+</pre>
+</div> </li>
+<li> Side-effecting code referencing <var>symbol</var> is undefined. Avoid. For example, here are two similar functions. Both use <code>and</code>, <var>symbol</var> and <code>guard</code>: <div class="example"> <pre class="example">(defun square-double-digit-p/CLEAN (integer)
+ (pcase (* integer integer)
+ ((and n (guard (&lt; 9 n 100))) (list 'yes n))
+ (sorry (list 'no sorry))))
+
+(square-double-digit-p/CLEAN 9) ⇒ (yes 81)
+(square-double-digit-p/CLEAN 3) ⇒ (no 9)
+</pre>
+
+<pre class="example">(defun square-double-digit-p/MAYBE (integer)
+ (pcase (* integer integer)
+ ((and n (guard (&lt; 9 (incf n) 100))) (list 'yes n))
+ (sorry (list 'no sorry))))
+
+(square-double-digit-p/MAYBE 9) ⇒ (yes 81)
+(square-double-digit-p/MAYBE 3) ⇒ (yes 9) ; <span class="roman">WRONG!</span>
+</pre>
+</div> <p>The difference is in <var>boolean-expression</var> in <code>guard</code>: <code>CLEAN</code> references <code>n</code> simply and directly, while <code>MAYBE</code> references <code>n</code> with a side-effect, in the expression <code>(incf n)</code>. When <code>integer</code> is 3, here’s what happens: </p> <ul> <li> The first <code>n</code> binds it to <var>expval</var>, i.e., the result of evaluating <code>(* 3 3)</code>, or 9. </li>
+<li> <var>boolean-expression</var> is evaluated: <div class="example"> <pre class="example">start: (&lt; 9 (incf n) 100)
+becomes: (&lt; 9 (setq n (1+ n)) 100)
+becomes: (&lt; 9 (setq n (1+ 9)) 100)
+</pre>
+<pre class="example">becomes: (&lt; 9 (setq n 10) 100)
+ ; <span class="roman">side-effect here!</span>
+becomes: (&lt; 9 n 100) ; <span class="roman"><code>n</code> now bound to 10</span>
+becomes: (&lt; 9 10 100)
+becomes: t
+</pre>
+</div> </li>
+<li> Because the result of the evaluation is non-<code>nil</code>, <code>guard</code> matches, <code>and</code> matches, and control passes to that clause’s body forms. </li>
+</ul> <p>Aside from the mathematical incorrectness of asserting that 9 is a double-digit integer, there is another problem with <code>MAYBE</code>. The body form references <code>n</code> once more, yet we do not see the updated value—10—at all. What happened to it? </p> <p>To sum up, it’s best to avoid side-effecting references to <var>symbol</var> patterns entirely, not only in <var>boolean-expression</var> (in <code>guard</code>), but also in <var>expr</var> (in <code>let</code>) and <var>function</var> (in <code>pred</code> and <code>app</code>). </p> </li>
+<li> On match, the clause’s body forms can reference the set of symbols the pattern let-binds. When <var>seqpat</var> is <code>and</code>, this set is the union of all the symbols each of its sub-patterns let-binds. This makes sense because, for <code>and</code> to match, all the sub-patterns must match. <p>When <var>seqpat</var> is <code>or</code>, things are different: <code>or</code> matches at the first sub-pattern that matches; the rest of the sub-patterns are ignored. It makes no sense for each sub-pattern to let-bind a different set of symbols because the body forms have no way to distinguish which sub-pattern matched and choose among the different sets. For example, the following is invalid: </p> <div class="example"> <pre class="example">(require 'cl-lib)
+(pcase (read-number "Enter an integer: ")
+ ((or (and (pred cl-evenp)
+ e-num) ; <span class="roman">bind <code>e-num</code> to <var>expval</var></span>
+ o-num) ; <span class="roman">bind <code>o-num</code> to <var>expval</var></span>
+ (list e-num o-num)))
+</pre>
+
+<pre class="example">Enter an integer: 42
+error→ Symbol’s value as variable is void: o-num
+</pre>
+<pre class="example">Enter an integer: 149
+error→ Symbol’s value as variable is void: e-num
+</pre>
+</div> <p>Evaluating body form <code>(list <span class="nolinebreak">e-num</span> <span class="nolinebreak">o-num)</span></code> signals error. To distinguish between sub-patterns, you can use another symbol, identical in name in all sub-patterns but differing in value. Reworking the above example: </p> <div class="example"> <pre class="example">(require 'cl-lib)
+(pcase (read-number "Enter an integer: ")
+ ((and num ; <span class="roman">line 1</span>
+ (or (and (pred cl-evenp) ; <span class="roman">line 2</span>
+ (let spin 'even)) ; <span class="roman">line 3</span>
+ (let spin 'odd))) ; <span class="roman">line 4</span>
+ (list spin num))) ; <span class="roman">line 5</span>
+</pre>
+
+<pre class="example">Enter an integer: 42
+⇒ (even 42)
+</pre>
+<pre class="example">Enter an integer: 149
+⇒ (odd 149)
+</pre>
+</div> <p>Line 1 “factors out” the <var>expval</var> binding with <code>and</code> and <var>symbol</var> (in this case, <code>num</code>). On line 2, <code>or</code> begins in the same way as before, but instead of binding different symbols, uses <code>let</code> twice (lines 3-4) to bind the same symbol <code>spin</code> in both sub-patterns. The value of <code>spin</code> distinguishes the sub-patterns. The body form references both symbols (line 5). </p>
+</li>
+</ol><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/pcase-Macro.html" class="_attribution-link">https://www.gnu.org/software/emacs/manual/html_node/elisp/pcase-Macro.html</a>
+ </p>
+</div>