emacs-diffs
[Top][All Lists]
Advanced

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

[Emacs-diffs] emacs-26 e824c91: Improve documentation of destructuring-b


From: Eli Zaretskii
Subject: [Emacs-diffs] emacs-26 e824c91: Improve documentation of destructuring-binding macros
Date: Sat, 3 Nov 2018 09:13:00 -0400 (EDT)

branch: emacs-26
commit e824c914dabd92537a0d6e44eaa10bb4699c312f
Author: Eli Zaretskii <address@hidden>
Commit: Eli Zaretskii <address@hidden>

    Improve documentation of destructuring-binding macros
    
    * lisp/emacs-lisp/pcase.el (pcase-dolist, pcase-let)
    (pcase-let*): Improve the doc strings.
    
    * doc/lispref/sequences.texi (Sequence Functions): Improve
    wording and rename arguments of seq-let to be more
    descriptive.  Add a cross-reference to "Destructuring with
    pcase Patterns".
    * doc/lispref/control.texi (Pattern-Matching Conditional):
    Improve wording and the menu.
    (pcase Macro): Incorporate patch suggested by Paul Eggert
    <address@hidden>.  Reformat text.
    (Destructuring with pcase Patterns): Rename from
    "Destructuring patterns", and improve wording and indexing.
---
 doc/lispref/control.texi   | 228 ++++++++++++++++++++++++---------------------
 doc/lispref/sequences.texi |  20 ++--
 lisp/emacs-lisp/pcase.el   |  43 +++++----
 3 files changed, 160 insertions(+), 131 deletions(-)

diff --git a/doc/lispref/control.texi b/doc/lispref/control.texi
index 06c6622..f80622e 100644
--- a/doc/lispref/control.texi
+++ b/doc/lispref/control.texi
@@ -419,65 +419,68 @@ This is not completely equivalent because it can evaluate 
@var{arg1} or
 @node Pattern-Matching Conditional
 @section Pattern-Matching Conditional
 @cindex pcase
address@hidden pattern matching
address@hidden pattern matching, programming style
 
 Aside from the four basic conditional forms, Emacs Lisp also
 has a pattern-matching conditional form, the @code{pcase} macro,
 a hybrid of @code{cond} and @code{cl-case}
 (@pxref{Conditionals,,,cl,Common Lisp Extensions})
 that overcomes their limitations and introduces
-the @dfn{pattern matching} programming style.
-First, the limitations:
+the @dfn{pattern matching programming style}.
+The limitations that @code{pcase} overcomes are:
 
 @itemize
address@hidden The @code{cond} form chooses among alternatives
-by evaluating the predicate @var{condition} of each
-of its clauses (@pxref{Conditionals}).
-The primary limitation is that variables let-bound in @var{condition}
-are not available to the clause's @var{body-forms}.
address@hidden
+The @code{cond} form chooses among alternatives by evaluating the
+predicate @var{condition} of each of its clauses
+(@pxref{Conditionals}).  The primary limitation is that variables
+let-bound in @var{condition} are not available to the clause's
address@hidden
 
 Another annoyance (more an inconvenience than a limitation)
 is that when a series of @var{condition} predicates implement
-equality tests, there is a lot of repeated code.
-For that, why not use @code{cl-case}?
+equality tests, there is a lot of repeated code.  (@code{cl-case}
+solves this inconvenience.)
 
 @item
 The @code{cl-case} macro chooses among alternatives by evaluating
 the equality of its first argument against a set of specific
 values.
-The limitations are two-fold:
+
+Its limitations are two-fold:
 
 @enumerate
address@hidden The equality tests use @code{eql}.
address@hidden The values must be known and written in advance.
address@hidden
+The equality tests use @code{eql}.
address@hidden
+The values must be known and written in advance.
 @end enumerate
 
 @noindent
 These render @code{cl-case} unsuitable for strings or compound
-data structures (e.g., lists or vectors).
-For that, why not use @code{cond}?
-(And here we end up in a circle.)
+data structures (e.g., lists or vectors).  (@code{cond} doesn't have
+these limitations, but it has others, see above.)
 @end itemize
 
 @noindent
 Conceptually, the @code{pcase} macro borrows the first-arg focus
 of @code{cl-case} and the clause-processing flow of @code{cond},
 replacing @var{condition} with a generalization of
-the equality test called @dfn{matching},
+the equality test which is a variant of @dfn{pattern matching},
 and adding facilities so that you can concisely express a
 clause's predicate, and arrange to share let-bindings between
 a clause's predicate and @var{body-forms}.
 
 The concise expression of a predicate is known as a @dfn{pattern}.
-When the predicate, called on the value of the first arg,
-returns address@hidden, the pattern matches the value
-(or sometimes ``the value matches the pattern'').
+When the predicate, called on the value of the first arg, returns
address@hidden, we say that ``the pattern matches the value'' (or
+sometimes ``the value matches the pattern'').
 
 @menu
-* The @code{pcase} macro: pcase Macro.  Plus examples and caveats.
+* The @code{pcase} macro: pcase Macro.  Includes examples and caveats.
 * Extending @code{pcase}: Extending pcase.  Define new kinds of patterns.
-* Backquote-Style Patterns: Backquote Patterns.  Structural matching.
-* Destructuring patterns:: Using pcase patterns to extract subfields.
+* Backquote-Style Patterns: Backquote Patterns.  Structural patterns matching.
+* Destructuring with pcase Patterns:: Using pcase patterns to extract 
subfields.
 @end menu
 
 @node pcase Macro
@@ -498,30 +501,30 @@ of the last of @var{body-forms} in the successful clause.
 Otherwise, @code{pcase} evaluates to @code{nil}.
 @end defmac
 
-Each @var{pattern} has to be a @dfn{pcase pattern}, which can either
-use one of the core patterns defined below, or use one of the patterns
-defined via @code{pcase-defmacro}.
address@hidden pcase pattern
+Each @var{pattern} has to be a @dfn{pcase pattern}, which can use
+either one of the core patterns defined below, or one of the patterns
+defined via @code{pcase-defmacro} (@pxref{Extending pcase}).
 
-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:
+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:
 
 @table @code
 
 @item _
 Matches any @var{expval}.
-This is known as @dfn{don't care} or @dfn{wildcard}.
+This is also known as @dfn{don't care} or @dfn{wildcard}.
 
 @item '@var{val}
-Matches if @var{expval} is @code{equal} to @var{val}.
+Matches if @var{expval} is equals @var{val}.  The comparison is done
+as if by @code{equal} (@pxref{Equality Predicates}).
 
 @item @var{keyword}
 @itemx @var{integer}
 @itemx @var{string}
-Matches if @var{expval} is @code{equal} to the literal object.
+Matches if @var{expval} equals the literal object.
 This is a special case of @code{'@var{val}}, above,
 possible because literal objects of these types are self-quoting.
 
@@ -533,17 +536,17 @@ Matches any @var{expval}, and additionally let-binds 
@var{symbol} to
 If @var{symbol} is part of a sequencing pattern @var{seqpat}
 (e.g., by using @code{and}, below), the binding is also available to
 the portion of @var{seqpat} following the appearance of @var{symbol}.
-This usage has some caveats (@pxref{pcase-symbol-caveats,,caveats}).
+This usage has some caveats, see @ref{pcase-symbol-caveats,,caveats}.
 
 Two symbols to avoid are @code{t}, which behaves like @code{_}
-(above) and is deprecated, and @code{nil}, which signals error.
+(above) and is deprecated, and @code{nil}, which signals an error.
 Likewise, it makes no sense to bind keyword symbols
 (@pxref{Constant Variables}).
 
 @item (pred @var{function})
 Matches if the predicate @var{function} returns address@hidden
 when called on @var{expval}.
address@hidden can have one of the possible forms:
+the predicate @var{function} can have one of the following forms:
 
 @table @asis
 @item function name (a symbol)
@@ -570,20 +573,17 @@ the actual function call becomes: @address@hidden(= 42 
@var{expval})}}.
 @item (app @var{function} @var{pattern})
 Matches if @var{function} called on @var{expval} returns a
 value that matches @var{pattern}.
address@hidden can take one of the
-forms described for @code{pred}, above.
-Unlike @code{pred}, however,
address@hidden tests the result against @var{pattern},
-rather than against a boolean truth value.
address@hidden can take one of the forms described for @code{pred},
+above.  Unlike @code{pred}, however, @code{app} tests the result
+against @var{pattern}, rather than against a boolean truth value.
 
 @item (guard @var{boolean-expression})
 Matches if @var{boolean-expression} evaluates to address@hidden
 
 @item (let @var{pattern} @var{expr})
-Evaluates @var{expr} to get @var{exprval}
-and matches if @var{exprval} matches @var{pattern}.
-(It is called @code{let} because
address@hidden can bind symbols to values using @var{symbol}.)
+Evaluates @var{expr} to get @var{exprval} and matches if @var{exprval}
+matches @var{pattern}.  (It is called @code{let} because @var{pattern}
+can bind symbols to values using @var{symbol}.)
 @end table
 
 @cindex sequencing pattern
@@ -596,18 +596,16 @@ but instead of processing values, they process 
sub-patterns.
 
 @table @code
 @item (and @address@hidden)
-Attempts to match @address@hidden, in order,
-until one of them fails to match.
-In that case, @code{and} likewise fails to match,
-and the rest of the sub-patterns are not tested.
-If all sub-patterns match, @code{and} matches.
+Attempts to match @address@hidden, in order, until one of them
+fails to match.  In that case, @code{and} likewise fails to match, and
+the rest of the sub-patterns are not tested.  If all sub-patterns
+match, @code{and} matches.
 
 @item (or @var{pattern1} @address@hidden)
 Attempts to match @var{pattern1}, @var{pattern2}, @dots{}, in order,
-until one of them succeeds.
-In that case, @code{or} likewise matches,
-and the rest of the sub-patterns are not tested.
-(Note that there must be at least two sub-patterns.
+until one of them succeeds.  In that case, @code{or} likewise matches,
+and the rest of the sub-patterns are not tested.  (Note that there
+must be at least two sub-patterns.
 Simply @address@hidden(or @var{pattern1})}} signals error.)
 @c Issue: Is this correct and intended?
 @c        Are there exceptions, qualifications?
@@ -1042,12 +1040,11 @@ Both use a single backquote construct 
(@pxref{Backquote}).
 
 This subsection describes @dfn{backquote-style patterns},
 a set of builtin patterns that eases structural matching.
-For background, @xref{Pattern-Matching Conditional}.
+For background, @pxref{Pattern-Matching Conditional}.
 
address@hidden patterns} are a powerful set of
address@hidden pattern extensions (created using @code{pcase-defmacro})
-that make it easy to match @var{expval} against
-specifications of its @emph{structure}.
+Backquote-style patterns are a powerful set of @code{pcase} pattern
+extensions (created using @code{pcase-defmacro}) that make it easy to
+match @var{expval} against specifications of its @emph{structure}.
 
 For example, to match @var{expval} that must be a list of two
 elements whose first element is a specific string and the second
@@ -1173,87 +1170,102 @@ evaluation results:
 (evaluate '(sub 1 2) nil)                 @result{} error
 @end example
 
address@hidden Destructuring patterns
address@hidden Destructuring Patterns
address@hidden destructuring patterns
address@hidden Destructuring with pcase Patterns
address@hidden Destructuring with @code{pcase} Patterns
address@hidden destructuring with pcase patterns
 
 Pcase patterns not only express a condition on the form of the objects
-they can match but they can also extract sub-fields of those objects.
-Say we have a list and want to extract 2 elements from it with the
-following code:
+they can match, but they can also extract sub-fields of those objects.
+For example we can extract 2 elements from a list that is the value of
+the variable @code{my-list} with the following code:
 
 @example
-  (pcase l
+  (pcase my-list
     (`(add ,x ,y)  (message "Contains %S and %S" x y)))
 @end example
 
 This will not only extract @code{x} and @code{y} but will additionally
-test that @code{l} is a list containing exactly 3 elements and whose
-first element is the symbol @code{add}.  If any of those tests fail,
address@hidden will directly return @code{nil} without calling
+test that @code{my-list} is a list containing exactly 3 elements and
+whose first element is the symbol @code{add}.  If any of those tests
+fail, @code{pcase} will immediately return @code{nil} without calling
 @code{message}.
 
address@hidden of an object is an operation that extracts
-multiple values stored in the object, e.g., the 2nd and the 3rd
-element of a list or a vector.  @dfn{Destructuring binding} is
-similar to a local binding (@pxref{Local Variables}), but it gives
-values to multiple elements of a variable by extracting those values
-from an object of compatible structure.
+Extraction of multiple values stored in an object is known as
address@hidden  Using @code{pcase} patterns allows to perform
address@hidden binding}, which is similar to a local binding
+(@pxref{Local Variables}), but gives values to multiple elements of
+a variable by extracting those values from an object of compatible
+structure.
 
-The macros described in this section use @dfn{destructuring
-patterns}, which are normal Pcase patterns used in a context where we
-presume that the object does match the pattern, and we only want
-to extract some subfields.  For example:
+The macros described in this section use @code{pcase} patterns to
+perform destructuring binding.  The condition of the object to be of
+compatible structure means that the object must match the pattern,
+because only then the object's subfields can be extracted.  For
+example:
 
 @example
-  (pcase-let ((`(add ,x ,y) l))
+  (pcase-let ((`(add ,x ,y) my-list))
     (message "Contains %S and %S" x y))
 @end example
 
 @noindent
 does the same as the previous example, except that it directly tries
-to extract @code{x} and @code{y} from @code{l} without first verifying
-if @code{l} is a list which has the right number of elements and has
address@hidden as its first element.
-The precise behavior when the object does not actually match the
-pattern is undefined, although the body will not be silently skipped:
-either an error is signaled or the body is run with some of the
-variables potentially bound to arbitrary values like @code{nil}.
+to extract @code{x} and @code{y} from @code{my-list} without first
+verifying if @code{my-list} is a list which has the right number of
+elements and has @code{add} as its first element.  The precise
+behavior when the object does not actually match the pattern is
+undefined, although the body will not be silently skipped: either an
+error is signaled or the body is run with some of the variables
+potentially bound to arbitrary values like @code{nil}.
+
+The pcase patterns that are useful for destructuring bindings are
+generally those described in @ref{Backquote Patterns}, since they
+express a specification of the structure of objects that will match.
+
+For an alternative facility for destructuring binding, see
address@hidden
 
 @defmac pcase-let bindings address@hidden
-Bind variables according to @var{bindings} and then eval @var{body}.
+Perform desctructuring binding of variables according to
address@hidden, and then evaluate @var{body}.
 
 @var{bindings} is a list of bindings of the form @address@hidden(@var{pattern}
 @var{exp})}}, where @var{exp} is an expression to evaluate and
address@hidden is a destructuring pattern.
address@hidden is a @code{pcase} pattern.
 
-All @var{exp}s are evaluated first after which they are matched
+All @var{exp}s are evaluated first, after which they are matched
 against their respective @var{pattern}, introducing new variable
-bindings which can then be used inside @var{body}.
+bindings that can then be used inside @var{body}.  The variable
+bindings are produced by destructuring binding of elements of
address@hidden to the values of the corresponding elements of the
+evaluated @var{exp}.
 @end defmac
 
 @defmac pcase-let* bindings address@hidden
-Bind variables according to @var{bindings} and then eval @var{body}.
+Perform desctructuring binding of variables according to
address@hidden, and then evaluate @var{body}.
 
 @var{bindings} is a list of bindings of the form @code{(@var{pattern}
 @var{exp})}, where @var{exp} is an expression to evaluate and
address@hidden is a destructuring pattern.
-
-Unlike @code{pcase-let}, but like @code{let*}, each @var{exp} is
-matched against its corresponding @var{pattern} before passing to the
-next element of @var{bindings}, so the variables introduced in each
-binding are available in the @var{exp}s that follow it, additionally
-to being available in @var{body}.
address@hidden is a @code{pcase} pattern.  The variable bindings are
+produced by destructuring binding of elements of @var{pattern} to the
+values of the corresponding elements of the evaluated @var{exp}.
+
+Unlike @code{pcase-let}, but similarly to @code{let*}, each @var{exp}
+is matched against its corresponding @var{pattern} before processing
+the next element of @var{bindings}, so the variable bindings
+introduced in each one of the @var{bindings} are available in the
address@hidden of the @var{bindings} that follow it, additionally to
+being available in @var{body}.
 @end defmac
 
address@hidden dolist
 @defmac pcase-dolist (pattern list) address@hidden
-This construct executes @var{body} once for each element of
address@hidden, in a context where the variables appearing in the the
-destructuring pattern @var{pattern} are bound to the corresponding
-values found in the element.
-When @var{pattern} is a simple variable, this ends up being equivalent
-to @code{dolist}.
+Execute @var{body} once for each element of @var{list}, on each
+iteration performing a destructuring binding of variables in
address@hidden to the values of the corresponding subfields of the
+element of @var{list}.  The bindings are performed as if by
address@hidden  When @var{pattern} is a simple variable, this ends
+up being equivalent to @code{dolist} (@pxref{Iteration}).
 @end defmac
 
 
diff --git a/doc/lispref/sequences.texi b/doc/lispref/sequences.texi
index 51d724c..60d017c 100644
--- a/doc/lispref/sequences.texi
+++ b/doc/lispref/sequences.texi
@@ -1049,15 +1049,18 @@ that @var{sequence} can be a list, vector or string.  
This is
 primarily useful for side-effects.
 @end defmac
 
address@hidden seq-let arguments sequence address@hidden
address@hidden
address@hidden seq-let var-sequence val-sequence address@hidden
 @cindex sequence destructuring
-  This macro binds the variables defined in @var{arguments} to the
-elements of @var{sequence}.  @var{arguments} can themselves include
-sequences, allowing for nested destructuring.
+  This macro binds the variables defined in @var{var-sequence} to the
+values that are the corresponding elements of @var{val-sequence}.
+This is known as @dfn{destructuring binding}.  The elements of
address@hidden can themselves include sequences, allowing for
+nested destructuring.
 
-The @var{arguments} sequence can also include the @code{&rest} marker
-followed by a variable name to be bound to the rest of
address@hidden
+The @var{var-sequence} sequence can also include the @code{&rest}
+marker followed by a variable name to be bound to the rest of
address@hidden
 
 @example
 @group
@@ -1081,6 +1084,9 @@ followed by a variable name to be bound to the rest of
 @end group
 @result{} [3 4]
 @end example
+
+The @code{pcase} patterns provide an alternative facility for
+destructuring binding, see @ref{Destructuring with pcase Patterns}.
 @end defmac
 
 @defun seq-random-elt sequence
diff --git a/lisp/emacs-lisp/pcase.el b/lisp/emacs-lisp/pcase.el
index 2e89ae0..fde3bdb 100644
--- a/lisp/emacs-lisp/pcase.el
+++ b/lisp/emacs-lisp/pcase.el
@@ -264,10 +264,14 @@ variable name being but a special case of it)."
 
 ;;;###autoload
 (defmacro pcase-let* (bindings &rest body)
-  "Like `let*' but where you can use `pcase' patterns for bindings.
-BODY should be an expression, and BINDINGS should be a list of bindings
-of the form (PATTERN EXP).
-See `pcase-let' for discussion of how PATTERN is matched."
+  "Like `let*', but supports destructuring BINDINGS using `pcase' patterns.
+As with `pcase-let', BINDINGS are of the form (PATTERN EXP), but the
+EXP in each binding in BINDINGS can use the results of the destructuring
+bindings that precede it in BINDINGS' order.
+
+Each EXP should match (i.e. be of compatible structure) to its
+respective PATTERN; a mismatch may signal an error or may go
+undetected, binding variables to arbitrary values, such as nil."
   (declare (indent 1)
            (debug ((&rest (pcase-PAT &optional form)) body)))
   (let ((cached (gethash bindings pcase--memoize)))
@@ -280,13 +284,16 @@ See `pcase-let' for discussion of how PATTERN is matched."
 
 ;;;###autoload
 (defmacro pcase-let (bindings &rest body)
-  "Like `let' but where you can use `pcase' patterns for bindings.
-BODY should be a list of expressions, and BINDINGS should be a list of bindings
-of the form (PATTERN EXP).
-The PATTERNs are only used to extract data, so the code does not test
-whether the data does match the corresponding patterns: a mismatch
-may signal an error or may go undetected, binding variables to arbitrary
-values, such as nil."
+  "Like `let', but supports destructuring BINDINGS using `pcase' patterns.
+BODY should be a list of expressions, and BINDINGS should be a list of
+bindings of the form (PATTERN EXP).
+All EXPs are evaluated first, and then used to perform destructuring
+bindings by matching each EXP against its respective PATTERN.  Then
+BODY is evaluated with those bindings in effect.
+
+Each EXP should match (i.e. be of compatible structure) to its
+respective PATTERN; a mismatch may signal an error or may go
+undetected, binding variables to arbitrary values, such as nil."
   (declare (indent 1) (debug pcase-let*))
   (if (null (cdr bindings))
       `(pcase-let* ,bindings ,@body)
@@ -304,11 +311,15 @@ values, such as nil."
 
 ;;;###autoload
 (defmacro pcase-dolist (spec &rest body)
-  "Superset of `dolist' where the VAR binding can be a `pcase' PATTERN.
-More specifically, this is just a shorthand for the following combination
-of `dolist' and `pcase-let':
-
-    (dolist (x LIST) (pcase-let ((PATTERN x)) BODY...))
+  "Eval BODY once for each set of bindings defined by PATTERN and LIST 
elements.
+PATTERN should be a `pcase' pattern describing the structure of
+LIST elements, and LIST is a list of objects that match PATTERN,
+i.e. have a structure that is compatible with PATTERN.
+For each element of LIST, this macro binds the variables in
+PATTERN to the corresponding subfields of the LIST element, and
+then evaluates BODY with these bindings in effect.  The
+destructuring bindings of variables in PATTERN to the subfields
+of the elements of LIST is performed as if by `pcase-let'.
 \n(fn (PATTERN LIST) BODY...)"
   (declare (indent 1) (debug ((pcase-PAT form) body)))
   (if (pcase--trivial-upat-p (car spec))



reply via email to

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