From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.org!.POSTED!not-for-mail From: Stefan Monnier Newsgroups: gmane.emacs.devel Subject: Re: Replace trivial pcase occurrences in the Emacs sources Date: Tue, 30 Oct 2018 15:21:52 -0400 Message-ID: References: <83tvlcsnee.fsf@gnu.org> <86mur137n8.fsf@gmail.com> <20181029130132.GB4195@ACM> <20181029134722.GC4195@ACM> <87lg6gifnb.fsf@web.de> <87muqwxs7m.fsf@ericabrahamsen.net> <83h8h3jlyd.fsf@gnu.org> NNTP-Posting-Host: blaine.gmane.org Mime-Version: 1.0 Content-Type: text/plain X-Trace: blaine.gmane.org 1540927388 30887 195.159.176.226 (30 Oct 2018 19:23:08 GMT) X-Complaints-To: usenet@blaine.gmane.org NNTP-Posting-Date: Tue, 30 Oct 2018 19:23:08 +0000 (UTC) User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/27.0.50 (gnu/linux) To: emacs-devel@gnu.org Original-X-From: emacs-devel-bounces+ged-emacs-devel=m.gmane.org@gnu.org Tue Oct 30 20:23:04 2018 Return-path: Envelope-to: ged-emacs-devel@m.gmane.org Original-Received: from lists.gnu.org ([208.118.235.17]) by blaine.gmane.org with esmtp (Exim 4.84_2) (envelope-from ) id 1gHZbQ-0007s2-Lh for ged-emacs-devel@m.gmane.org; Tue, 30 Oct 2018 20:23:00 +0100 Original-Received: from localhost ([::1]:55121 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1gHZdX-00030O-7z for ged-emacs-devel@m.gmane.org; Tue, 30 Oct 2018 15:25:11 -0400 Original-Received: from eggs.gnu.org ([2001:4830:134:3::10]:39628) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1gHZad-0008HD-6p for emacs-devel@gnu.org; Tue, 30 Oct 2018 15:22:12 -0400 Original-Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1gHZaY-0000wU-1s for emacs-devel@gnu.org; Tue, 30 Oct 2018 15:22:11 -0400 Original-Received: from [195.159.176.226] (port=38076 helo=blaine.gmane.org) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1gHZaW-0000ob-3b for emacs-devel@gnu.org; Tue, 30 Oct 2018 15:22:05 -0400 Original-Received: from list by blaine.gmane.org with local (Exim 4.84_2) (envelope-from ) id 1gHZYL-00040d-5q for emacs-devel@gnu.org; Tue, 30 Oct 2018 20:19:49 +0100 X-Injected-Via-Gmane: http://gmane.org/ Original-Lines: 196 Original-X-Complaints-To: usenet@blaine.gmane.org Cancel-Lock: sha1:Bl9GDFPSlFDhk32MpBGyJHQZHl8= X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] X-Received-From: 195.159.176.226 X-BeenThere: emacs-devel@gnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: "Emacs development discussions." List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: emacs-devel-bounces+ged-emacs-devel=m.gmane.org@gnu.org Original-Sender: "Emacs-devel" Xref: news.gmane.org gmane.emacs.devel:230849 Archived-At: >> +* Destructuring patterns:: Using pcase patterns to extract subfields. > We never used "pcase patterns" in the manual before, so I wonder > whether we should start now. If we want to do that, this should be > defined before it is used. I'm uncomfortable using "pattern" to refer to "pcase pattern" unless the context makes it clear. I'm not completely sure where best to define pcase patterns. >> +@node Destructuring patterns >> +@subsection Destructuring Patterns >> +@cindex Destructuring patterns > > By convention, index entries should start with a lower-case letter. Fixed. >> +The macros described in this section use @emph{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. > > I think we need to define "destructuring" here (or elsewhere in the > manual, and have a cross-reference there in this section). The paragraph you quoted is exactly what I consider the definition of "destructuring pattern" (I don't see a need to define "destructuring" separately: the word placed in front of "pattern" is here treated as a kind of "proper name", just chosen so that it will help some if they already know the term from elsewhere, such as cl-destructuring-bind). > Readers that aren't familiar with that term will not be able to > understand why this word is used here. We need to start this with > something like > > @dfn{Destructuring} means ... I'd rather rename those to "Monnier patterns" and avoid the problem, if that's what it takes. > It would also help to tell what exactly makes a pattern a > destructuring one. As the paragraph says: it's the context in which it's used. > You want the text after the example to start like this: > > @noindent > does the same as ... > > Otherwise, this sentence sounds awkward, and will also be indented. Thanks. >> +@var{bindings} is a list of bindings of the form @code{(@var{pattern} >> +@var{exp})} > > Please use @w{..} around this form, so that it doesn't get broken > between two lines. Done. >> +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}. > AFAIU, this means only some of the pcase patterns make sense in this > context. If that is true, I'd suggest ti somehow tell which are (or > which aren't, if that's easier). Not sure what you're thinking of. >> +@defmac pcase-dolist (pattern list) body@dots{} >> +This construct executes @var{body} once for each element of >> +@var{list}, in a context where the destructuring pattern >> +@var{pattern} was matched against the element. > > I don't think I understand what "in a context where the pattern was > matched" means here. Is any aspect of the match except destructuring > bindings relevant to execution of the body? No. But those extra bindings are exactly the context I'm referring to. In my work, "context" and "environment" are the usual words used to refer to the map that links identifiers to their corresponding information (typically, type or value depending on the ...ahem... context). Stefan diff --git a/doc/lispref/control.texi b/doc/lispref/control.texi index 5be4b298b4..da6a240ddc 100644 --- a/doc/lispref/control.texi +++ b/doc/lispref/control.texi @@ -477,6 +477,7 @@ Pattern-Matching Conditional * The @code{pcase} macro: pcase Macro. Plus 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. @end menu @node pcase Macro @@ -497,6 +498,10 @@ pcase Macro 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}. + The rest of this subsection describes different forms of core patterns, presents some examples, @@ -1168,6 +1173,82 @@ Backquote Patterns (evaluate '(sub 1 2) nil) @result{} error @end example +@node Destructuring patterns +@subsection Destructuring Patterns +@cindex destructuring 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: + +@example + (pcase l + (`(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, +@code{pcase} will directly return @code{nil} without calling +@code{message}. + +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: + +@example + (pcase-let ((`(add ,x ,y) l)) + (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 +@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}. + +@defmac pcase-let bindings body@dots{} +Bind variables according to @var{bindings} and then eval @var{body}. + +@var{bindings} is a list of bindings of the form @w{@code{(@var{pattern} +@var{exp})}}, where @var{exp} is an expression to evaluate and +@var{pattern} is a destructuring pattern. + +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}. +@end defmac + +@defmac pcase-let* bindings body@dots{} +Bind variables according to @var{bindings} and then eval @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 +@var{pattern} 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}. +@end defmac + +@findex dolist +@defmac pcase-dolist (pattern list) body@dots{} +This construct executes @var{body} once for each element of +@var{list}, in a context where the destructuring pattern +@var{pattern} was matched against the element. +When @var{pattern} is a simple variable, this ends up being equivalent +to @code{dolist}. +@end defmac + + @node Iteration @section Iteration @cindex iteration