emacs-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Emacs-diffs] emacs-25 1d4887a: Improve documentation of 'pcase'


From: Eli Zaretskii
Subject: [Emacs-diffs] emacs-25 1d4887a: Improve documentation of 'pcase'
Date: Sat, 23 Jan 2016 10:23:28 +0000

branch: emacs-25
commit 1d4887a3f35ffaf1f788cf5368e25d2cbf94ee94
Author: Eli Zaretskii <address@hidden>
Commit: Eli Zaretskii <address@hidden>

    Improve documentation of 'pcase'
    
    * doc/lispref/control.texi (Pattern matching case statement):
    Reorganize, expand, and improve wording.
    
    * etc/NEWS: Mention that 'pcase' changes are documented.
    
    Co-authored-by: John Wiegley <address@hidden>
    Co-authored-by: Michael Heerdegen <address@hidden>
---
 doc/lispref/control.texi |  224 ++++++++++++++++++++++++++++++---------------
 etc/NEWS                 |    2 +
 2 files changed, 151 insertions(+), 75 deletions(-)

diff --git a/doc/lispref/control.texi b/doc/lispref/control.texi
index 008a991..df60347 100644
--- a/doc/lispref/control.texi
+++ b/doc/lispref/control.texi
@@ -297,36 +297,147 @@ For example:
 @cindex pcase
 @cindex pattern matching
 
-To compare a particular value against various possible cases, the macro
address@hidden can come handy.  It takes the following form:
+The @code{cond} form lets you choose between alternatives using
+predicate conditions that compare values of expressions against
+specific values known and written in advance.  However, sometimes it
+is useful to select alternatives based on more general conditions that
+distinguish between broad classes of values.  The @code{pcase} macro
+allows to choose between alternatives based on matching the value of
+an expression against a series of patterns.  A pattern can be a
+literal value (comparison to literal values is what @code{cond} does),
+or it can be a more general description of the expected structure of
+the expression's value.
+
address@hidden pcase expression &rest clauses
+Evaluate @var{expression} and choose among an arbitrary number of
+alternatives based on the value of @var{expression}.  The possible
+alternatives are specified by @var{clauses}, each of which must be a
+list of the form @code{(@var{pattern} @var{body-forms})}.
address@hidden tries to match the value of @var{expression} to the
address@hidden of each clause, in textual order.  If the value matches,
+the clause succeeds; @code{pcase} then evaluates its @var{body-forms},
+and returns the value of the last of @var{body-forms}.  Any remaining
address@hidden are ignored.
+
+The @var{pattern} part of a clause can be of one of two types:
address@hidden, a pattern quoted with a backquote; or a
address@hidden, which is not quoted.  UPatterns are simpler, so we
+describe them first.
+
+Note: In the description of the patterns below, we use ``the value
+being matched'' to refer to the value of the @var{expression} that is
+the first argument of @code{pcase}.
+
+A UPattern can have one of the following forms:
 
address@hidden
-(pcase @var{exp} @var{branch}1 @var{branch}2 @var{branch}3 @dots{})
address@hidden example
address@hidden @code
 
-where each @var{branch} takes the form @code{(@var{upattern}
address@hidden@dots{})}.
address@hidden '@var{val}
+Matches if the value being matched is @code{equal} to @var{val}.
address@hidden @var{atom}
+Matches any @var{atom}, which can be a keyword, a number, or a string.
+(These are self-quoting, so this kind of UPattern is actually a
+shorthand for @code{'@var{atom}}.)
address@hidden _
+Matches any value.  This is known as @dfn{don't care} or @dfn{wildcard}.
address@hidden @var{symbol}
+Matches any value, and additionally let-binds @var{symbol} to the
+value it matched, so that you can later refer to it, either in the
address@hidden or also later in the pattern.
address@hidden (pred @var{predfun})
+Matches if the predicate function @var{predfun} returns address@hidden
+when called with the value being matched as its argument.
address@hidden can be one of the possible forms described below.
address@hidden (guard @var{boolean-expression})
+Matches if @var{boolean-expression} evaluates to address@hidden  This
+allows to include in a UPattern boolean conditions that refer to
+symbols bound to values (including the value being matched) by
+previous UPatterns.  Typically used inside an @code{and} UPattern, see
+below.  For example, @address@hidden(and x (guard (< x 10)))}} is a pattern
+which matches any number smaller than 10 and let-binds the variable
address@hidden to that number.
address@hidden (let @var{upattern} @var{expression})
+Matches if the specified @var{expression} matches the specified
address@hidden  This allows to match a pattern against the value of
+an @emph{arbitrary} expression, not just the expression that is the
+first argument to @code{pcase}.  (It is called @code{let} because
address@hidden can bind symbols to values using the @var{symbol}
+UPattern.)
address@hidden (app @var{function} @var{upattern})
+Matches if @var{function} applied to the value being matched returns a
+value that matches @var{upattern}.  This is like the @code{pred}
+UPattern, except that it tests the result against @var{UPattern},
+rather than against a boolean truth value.  The @var{function} call can
+use one of the forms described below.
address@hidden (or @var{upattern1} @address@hidden)
+Matches if one the argument UPatterns matches.  As soon as the first
+matching UPattern is found, the rest are not tested.  For this reason,
+if any of the UPatterns let-bind symbols to the matched value, they
+should all bind the same symbols.
address@hidden (and @var{upattern1} @address@hidden)
+Matches if all the argument UPatterns match.
address@hidden table
+
+The function calls used in the @code{pred} and @code{app} UPatterns
+can have one of the following forms:
+
address@hidden @asis
address@hidden function symbol, like @code{integerp}
+In this case, the named function is applied to the value being
+matched.
address@hidden lambda-function @code{(lambda (@var{arg}) @var{body})}
+In this case, the lambda-function is called with one argument, the
+value being matched.
address@hidden @code{(@var{func} @address@hidden)}
+This is a function call with @var{n} specified arguments; the function
+is called with these @var{n} arguments and an additional @var{n}+1-th
+argument that is the value being matched.
address@hidden table
 
-It will first evaluate @var{exp} and then compare the value against each
address@hidden to see which @var{branch} to use, after which it will run the
-corresponding @var{body-forms}.  A common use case is to distinguish
-between a few different constant values:
+Here's an illustrative example of using UPatterns:
 
address@hidden FIXME: This example should use every one of the UPatterns 
described
address@hidden above at least once.
 @example
 (pcase (get-return-code x)
-  (`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"))
+  ('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"))
   (code           (message "Unknown return code %S" code)))
 @end example
 
-In the last clause, @code{code} is a variable that gets bound to the value that
-was returned by @code{(get-return-code x)}.
+The QPatterns are more powerful.  They allow to match the value of the
address@hidden that is the first argument of @code{pcase} against
+specifications of its @emph{structure}.  For example, you can specify
+that the value must be a list of 2 elements whose first element is a
+string and the second element is a number.  QPatterns can have one of
+the following forms:
+
address@hidden @code
address@hidden `(@var{qpattern1} . @var{qpattern2})
+Matches if the value being matched is a cons cell whose @code{car}
+matches @var{qpattern1} and whose @code{cdr} matches @var{qpattern2}.
address@hidden address@hidden @var{qpattern2} @dots{} @var{qpatternm}]
+Matches if the value being matched is a vector of length @var{m} whose
address@hidden@code{(@var{m}-1)}th elements match @var{qpattern1},
address@hidden @dots{} @var{qpatternm}, respectively.
address@hidden `(,@var{upattern1} ,@var{upattern2} @dots{})
+Matches if the value being matched is a list whose elements match the
+corresponding @var{upattern1}, @var{upattern2}, etc.
address@hidden @var{atom}
+Matches if corresponding element of the value being matched is
address@hidden to the specified @var{atom}.
address@hidden ,@var{upattern}
+Matches if the corresponding element of the value being matched
+matches the specified @var{upattern}.
address@hidden table
+
address@hidden defmac
 
-To give a more complex example, a simple interpreter for a little
-expression language could look like (note that this example requires
-lexical binding):
+Here is an example of using @code{pcase} to implement a simple
+interpreter for a little expression language (note that this example
+requires lexical binding, @pxref{Lexical Binding}):
 
 @example
 (defun evaluate (exp env)
@@ -340,13 +451,19 @@ lexical binding):
     (_                  (error "Unknown expression %S" exp))))
 @end example
 
-Where @code{`(add ,x ,y)} is a pattern that checks that @code{exp} is a three
-element list starting with the symbol @code{add}, then extracts the second and
-third elements and binds them to the variables @code{x} and @code{y}.
address@hidden(pred numberp)} is a pattern that simply checks that @code{exp}
-is a number, and @code{_} is the catch-all pattern that matches anything.
+Here @code{`(add ,x ,y)} is a pattern that checks that @code{exp} is a
+three-element list starting with the literal symbol @code{add}, then
+extracts the second and third elements and binds them to the variables
address@hidden and @code{y}.  Then it evaluates @code{x} and @code{y} and
+adds the results.  The @code{call} and @code{fn} patterns similarly
+implement two flavors of function calls.  @code{(pred numberp)} is a
+pattern that simply checks that @code{exp} is a number and if so,
+evaluates it.  @code{(pred symbolp)} matches symbols, and returns
+their association.  Finally, @code{_} is the catch-all pattern that
+matches anything, so it's suitable for reporting syntax errors.
 
-Here are some sample programs including their evaluation results:
+Here are some sample programs in this small language, including their
+evaluation results:
 
 @example
 (evaluate '(add 1 2) nil)                 ;=> 3
@@ -355,56 +472,13 @@ Here are some sample programs including their evaluation 
results:
 (evaluate '(sub 1 2) nil)                 ;=> error
 @end example
 
-There are two kinds of patterns involved in @code{pcase}, called
address@hidden and @emph{Q-patterns}.  The @var{upattern} mentioned above
-are U-patterns and can take the following forms:
+Additional UPatterns can be defined using the @code{pcase-defmacro}
+macro.
 
address@hidden @code
address@hidden address@hidden
-This is one of the most common form of patterns.  The intention is to mimic the
-backquote macro: this pattern matches those values that could have been built
-by such a backquote expression.  Since we're pattern matching rather than
-building a value, the unquote does not indicate where to plug an expression,
-but instead it lets one specify a U-pattern that should match the value at
-that location.
-
-More specifically, a Q-pattern can take the following forms:
address@hidden @code
address@hidden (@var{qpattern1} . @var{qpattern2})
-This pattern matches any cons cell whose @code{car} matches @var{qpattern1} and
-whose @code{cdr} matches @var{qpattern2}.
address@hidden address@hidden @var{qpattern2} @dots{} @var{qpatternm}]
-This pattern matches a vector of length @var{M} whose 0..(@var{M}-1)th
-elements match @var{qpattern1}, @var{qpattern2} @dots{} @var{qpatternm},
-respectively.
address@hidden @var{atom}
-This pattern matches any atom @code{equal} to @var{atom}.
address@hidden ,@var{upattern}
-This pattern matches any object that matches the @var{upattern}.
address@hidden table
-
address@hidden @var{symbol}
-A mere symbol in a U-pattern matches anything, and additionally let-binds this
-symbol to the value that it matched, so that you can later refer to it, either
-in the @var{body-forms} or also later in the pattern.
address@hidden _
-This so-called @emph{don't care} pattern matches anything, like the previous
-one, but unlike symbol patterns it does not bind any variable.
address@hidden (pred @var{pred})
-This pattern matches if the function @var{pred} returns address@hidden when
-called with the object being matched.
address@hidden (or @var{upattern1} @address@hidden)
-This pattern matches as soon as one of the argument patterns succeeds.
-All argument patterns should let-bind the same variables.
address@hidden (and @var{upattern1} @address@hidden)
-This pattern matches only if all the argument patterns succeed.
address@hidden (guard @var{exp})
-This pattern ignores the object being examined and simply succeeds if @var{exp}
-evaluates to address@hidden and fails otherwise.  It is typically used inside
-an @code{and} pattern.  For example, @code{(and x (guard (< x 10)))}
-is a pattern which matches any number smaller than 10 and let-binds it to
-the variable @code{x}.
address@hidden table
address@hidden pcase-defmacro name args &rest body
+Define a new UPattern for @code{pcase}.  The UPattern will have the
+form @code{(@var{name} @var{args})}.
address@hidden defmac
 
 @node Combining Conditions
 @section Constructs for Combining Conditions
diff --git a/etc/NEWS b/etc/NEWS
index 7a0d2ef..048523a 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -1400,7 +1400,9 @@ that happen, `unhandled-file-name-directory' now defaults 
to calling
 * Lisp Changes in Emacs 25.1
 
 ** pcase
++++
 *** New UPatterns `quote', `app'.
++++
 *** New UPatterns can be defined with `pcase-defmacro'.
 +++
 *** New vector QPattern.



reply via email to

[Prev in Thread] Current Thread [Next in Thread]