* bug#70597: Problem in pcase-let? @ 2024-04-26 18:00 Marco Antoniotti 2024-04-27 16:11 ` Bruno Barbier 0 siblings, 1 reply; 18+ messages in thread From: Marco Antoniotti @ 2024-04-26 18:00 UTC (permalink / raw) To: 70597 [-- Attachment #1: Type: text/plain, Size: 846 bytes --] Hi This is for GNU Emacs 29.2 (build 2, x86_64-w64-mingw32) of 2024-02-01 running on Windows 11. I just noticed the following with pcase-let and pcase. I believe this is a problem with pcase-let. The following is a IELM transcript. The second plet-case should, IMHO, fail. ELISP> (pcase-let ((`(let ,bs (*when *,c . ,r)) '(let ((foo 42)) (*when *1 2 3)))) (list 'bs bs 'c c 'r r)) (bs ((foo 42)) c 1 r (2 3)) ELISP> (pcase-let ((`(let ,bs (*when *,c . ,r)) '(let ((foo 42)) (*zot *1 2 3)))) (list 'bs bs 'c c 'r r)) (bs ((foo 42)) c 1 r (2 3)) ELISP> (pcase '(let ((foo 42)) (*when *1 2 3)) (`(let ,bs (*zot *,c . ,r)) (list 'bs bs 'c c 'r r))) nil pcase correctly fails to match *when *and *zot*, while pcase-let seems to happily go ahead. All the best -- Marco Antoniotti Somewhere over the Rainbow [-- Attachment #2: Type: text/html, Size: 1819 bytes --] ^ permalink raw reply [flat|nested] 18+ messages in thread
* bug#70597: Problem in pcase-let? 2024-04-26 18:00 bug#70597: Problem in pcase-let? Marco Antoniotti @ 2024-04-27 16:11 ` Bruno Barbier 2024-04-27 22:28 ` Marco Antoniotti 0 siblings, 1 reply; 18+ messages in thread From: Bruno Barbier @ 2024-04-27 16:11 UTC (permalink / raw) To: Marco Antoniotti, 70597 Hi Marco, I'm not a maintainer but let me try to explain; I'm sure someone will correct me if I'm wrong. In short: not a bug. If I read your examples correctly, your problem could be reduced to this: (using org mode syntax, I hope it's ok): #+begin_src elisp (pcase-let ((`(A *,c . ,r) '(A *1 2 3))) (list c r)) #+end_src #+RESULTS: : (2 (3)) #+begin_src elisp (pcase-let ((`(A *,c . ,r) '(B *1 2 3))) (list c r)) #+end_src #+RESULTS: : (2 (3)) #+begin_src elisp (pcase '(A *1 2 3) (`(B *,c . ,r) (list c r))) #+end_src #+RESULTS: : nil The pcase-let documentation (describe-function 'pcase-let) says this: | Each EXP should match its respective PATTERN (i.e. be of structure | compatible to PATTERN); a mismatch may signal an error or may go | undetected, binding variables to arbitrary values, such as nil. Both of your pcase-let examples are actually undefined, because the patterns don't match in *both* cases. pcase-let works as documented: it did bind some variables to arbitrary values. That one matches (note the space between * and 1): #+begin_src elisp (pcase-let ((`(A * ,c . ,r) '(A * 1 2 3))) (list c r)) #+end_src #+RESULTS: : (1 (2 3)) That one doesn't match either (replacing * with WORD), but same result that your 2 pcase-let examples: #+begin_src elisp (pcase-let ((`(A *,c . ,r) '(A WORD1 2 3))) (list c r)) #+end_src #+RESULTS: : (2 (3)) Note that *1 is one symbol whose name is "*1". Your pattern `(*,c) is looking for the symbol whose name is "*", followed by the value for c. You may test your pattern, manually binding c to some value, to see that you get a list containing 2 values: #+begin_src elisp (let ((c 1)) `(*,c)) #+end_src #+RESULTS: : (* 1) Hoping this helps, Bruno ^ permalink raw reply [flat|nested] 18+ messages in thread
* bug#70597: Problem in pcase-let? 2024-04-27 16:11 ` Bruno Barbier @ 2024-04-27 22:28 ` Marco Antoniotti 2024-04-28 10:01 ` Bruno Barbier 2024-04-28 15:22 ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors 0 siblings, 2 replies; 18+ messages in thread From: Marco Antoniotti @ 2024-04-27 22:28 UTC (permalink / raw) To: Bruno Barbier; +Cc: 70597 [-- Attachment #1: Type: text/plain, Size: 3190 bytes --] Hi Bruno Thank you for the reply, but sorry. IMHO it is a bug, At a minimum, because pcase and pcase-let behave differently. I may be inclined to accept the explanation that the documentation about pcase-let allows for the behavior I find incorrect; that does not mean that the behavior is what is normally expected. Pattern matchers do ... pattern matching. If you allow quasiquotes or "incomplete specifications" (pick your preferred pattern matching terminology), then you should honor the expectations; hence two symbols that are not eq do not match. Also note that I do not have any star (*) operators in my examples. Again, the machinery is there, cfr, the example below, which selects the second clause. ELISP> *(pcase '(1 2 3 4) (`(1 2 ,x 5) (list 42 x)) (`(1 ,x 3 4) (list 666 x)))* *(666 2)* All the best MA On Sat, Apr 27, 2024 at 6:11 PM Bruno Barbier <brubar.cs@gmail.com> wrote: > > Hi Marco, > > I'm not a maintainer but let me try to explain; I'm sure someone will > correct me if I'm wrong. > > In short: not a bug. > > If I read your examples correctly, your problem could be reduced to this: > (using org mode syntax, I hope it's ok): > > #+begin_src elisp > (pcase-let > ((`(A *,c . ,r) '(A *1 2 3))) > (list c r)) > #+end_src > > #+RESULTS: > : (2 (3)) > > > #+begin_src elisp > (pcase-let > ((`(A *,c . ,r) '(B *1 2 3))) > (list c r)) > #+end_src > > #+RESULTS: > : (2 (3)) > > #+begin_src elisp > (pcase '(A *1 2 3) > (`(B *,c . ,r) (list c r))) > #+end_src > > #+RESULTS: > : nil > > > The pcase-let documentation (describe-function 'pcase-let) says this: > > | Each EXP should match its respective PATTERN (i.e. be of structure > | compatible to PATTERN); a mismatch may signal an error or may go > | undetected, binding variables to arbitrary values, such as nil. > > > Both of your pcase-let examples are actually undefined, because the > patterns don't match in *both* cases. pcase-let works as documented: > it did bind some variables to arbitrary values. > > That one matches (note the space between * and 1): > #+begin_src elisp > (pcase-let > ((`(A * ,c . ,r) '(A * 1 2 3))) > (list c r)) > #+end_src > > #+RESULTS: > : (1 (2 3)) > > That one doesn't match either (replacing * with WORD), but same > result that your 2 pcase-let examples: > #+begin_src elisp > (pcase-let > ((`(A *,c . ,r) '(A WORD1 2 3))) > (list c r)) > #+end_src > > #+RESULTS: > : (2 (3)) > > > Note that *1 is one symbol whose name is "*1". Your pattern `(*,c) is > looking for the symbol whose name is "*", followed by the value for c. > > You may test your pattern, manually binding c to some value, to see > that you get a list containing 2 values: > > #+begin_src elisp > (let ((c 1)) > `(*,c)) > #+end_src > > #+RESULTS: > : (* 1) > > Hoping this helps, > > Bruno > -- Marco Antoniotti Somewhere over the Rainbow [-- Attachment #2: Type: text/html, Size: 4512 bytes --] ^ permalink raw reply [flat|nested] 18+ messages in thread
* bug#70597: Problem in pcase-let? 2024-04-27 22:28 ` Marco Antoniotti @ 2024-04-28 10:01 ` Bruno Barbier 2024-04-28 10:07 ` Ihor Radchenko 2024-04-28 15:22 ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors 1 sibling, 1 reply; 18+ messages in thread From: Bruno Barbier @ 2024-04-28 10:01 UTC (permalink / raw) To: Marco Antoniotti; +Cc: 70597 Hi Marco, Marco Antoniotti <marcoxa@gmail.com> writes: > Hi Bruno > > Thank you for the reply, but sorry. IMHO it is a bug, At a minimum, > because pcase and pcase-let behave differently. > I may be inclined to accept the explanation that the documentation about > pcase-let allows for the behavior I find incorrect; that does not mean that > the behavior is what is normally expected. > > Pattern matchers do ... pattern matching. If you allow quasiquotes or > "incomplete specifications" (pick your preferred pattern matching > terminology), then you should honor the expectations; hence two symbols > that are not eq do not match. So, you would prefer for pcase-let to always signal an error if a pattern doesn't match. It makes sense. And it looks like the issue has already been raised: see bug#19670. (see https://debbugs.gnu.org/cgi/bugreport.cgi?bug=19670) > Also note that I do not have any star (*) operators in my examples. Thanks for mentionning this. I now see that you carefully crafted your HTML version, but, I only used the text version (that is less readable and contains plenty of stars). Sorry about the noise, explaining how to parse generated lightweight markup as elisp :) > Again, the machinery is there, cfr, the example below, which selects the > second clause. > > ELISP> > > *(pcase '(1 2 3 4) (`(1 2 ,x 5) (list 42 x)) (`(1 ,x 3 > 4) (list 666 x)))* > *(666 2)* I'm not sure it's that obvious: pcase doesn't really make a difference between match and no match: (eq (pcase 'b (`a t) (`b nil)) (pcase 'c (`a t) (`b nil))) ==> t If your request is really like bug#19670, further discussion should probably go there. All the best, Bruno ^ permalink raw reply [flat|nested] 18+ messages in thread
* bug#70597: Problem in pcase-let? 2024-04-28 10:01 ` Bruno Barbier @ 2024-04-28 10:07 ` Ihor Radchenko 2024-04-28 10:18 ` Eli Zaretskii 0 siblings, 1 reply; 18+ messages in thread From: Ihor Radchenko @ 2024-04-28 10:07 UTC (permalink / raw) To: Bruno Barbier; +Cc: Marco Antoniotti, 70597 Bruno Barbier <brubar.cs@gmail.com> writes: > So, you would prefer for pcase-let to always signal an error if a > pattern doesn't match. It makes sense. > > And it looks like the issue has already been raised: see bug#19670. > (see https://debbugs.gnu.org/cgi/bugreport.cgi?bug=19670) Also, see https://debbugs.gnu.org/cgi/bugreport.cgi?bug=68509 -- Ihor Radchenko // yantar92, Org mode contributor, Learn more about Org mode at <https://orgmode.org/>. Support Org development at <https://liberapay.com/org-mode>, or support my work at <https://liberapay.com/yantar92> ^ permalink raw reply [flat|nested] 18+ messages in thread
* bug#70597: Problem in pcase-let? 2024-04-28 10:07 ` Ihor Radchenko @ 2024-04-28 10:18 ` Eli Zaretskii 0 siblings, 0 replies; 18+ messages in thread From: Eli Zaretskii @ 2024-04-28 10:18 UTC (permalink / raw) To: Ihor Radchenko, Stefan Monnier; +Cc: brubar.cs, marcoxa, 70597 > Cc: Marco Antoniotti <marcoxa@gmail.com>, 70597@debbugs.gnu.org > From: Ihor Radchenko <yantar92@posteo.net> > Date: Sun, 28 Apr 2024 10:07:28 +0000 > > Bruno Barbier <brubar.cs@gmail.com> writes: > > > So, you would prefer for pcase-let to always signal an error if a > > pattern doesn't match. It makes sense. > > > > And it looks like the issue has already been raised: see bug#19670. > > (see https://debbugs.gnu.org/cgi/bugreport.cgi?bug=19670) > > Also, see https://debbugs.gnu.org/cgi/bugreport.cgi?bug=68509 Adding Stefan, in case he has comments. ^ permalink raw reply [flat|nested] 18+ messages in thread
* bug#70597: Problem in pcase-let? 2024-04-27 22:28 ` Marco Antoniotti 2024-04-28 10:01 ` Bruno Barbier @ 2024-04-28 15:22 ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors 2024-04-28 15:38 ` Marco Antoniotti 1 sibling, 1 reply; 18+ messages in thread From: Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors @ 2024-04-28 15:22 UTC (permalink / raw) To: Marco Antoniotti; +Cc: Bruno Barbier, 70597 > Pattern matchers do ... pattern matching. `pcase` is a pattern matcher. `pcase-let` is not: it performs "destructuring bindings". If you want to test if a pattern matches, then you want to use `pcase` or `pcase-exhaustive`, and not `pcase-let`. If you want a "one-branch `pcase-exhaustive` with a let-style notation", we could add such a thing of course, but I'd first like to see some evidence that it's useful in practice. Stefan ^ permalink raw reply [flat|nested] 18+ messages in thread
* bug#70597: Problem in pcase-let? 2024-04-28 15:22 ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors @ 2024-04-28 15:38 ` Marco Antoniotti 2024-04-28 17:05 ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors 0 siblings, 1 reply; 18+ messages in thread From: Marco Antoniotti @ 2024-04-28 15:38 UTC (permalink / raw) To: Stefan Monnier; +Cc: Bruno Barbier, 70597 [-- Attachment #1: Type: text/plain, Size: 1626 bytes --] Thank you all for the replies. Let me just answer the destructuring-bind comment by Stefan (I am answering to his last email). The previous ones are somewhat answered here as well. In some sense, yes. I kind of want destructuring-bind. It is, IMHO, unfortunate that ELisp does not have it and that we don't have cl-destructuring-bind either; lower level beast than matching, but useful. As per the pcase-let, I still think that the name and/or its behavior are confusing because of expectations about how a pattern matcher usually works. Of course you have the problems with "no matching" but that semantics can be dealt with separately, without surprising the user (at least me). And note that this is, IMHO, "surprising". *(pcase-let (`(foo bar ,x) '(bar foo 42)) x)* IMHO, this should either return nil or signal an error. With destructuring-bind* I would write (assuming indifference variables): *(destructuring-bind* (_ _ x) x)* All the best Marco On Sun, Apr 28, 2024 at 5:22 PM Stefan Monnier <monnier@iro.umontreal.ca> wrote: > > Pattern matchers do ... pattern matching. > > `pcase` is a pattern matcher. > `pcase-let` is not: it performs "destructuring bindings". > > If you want to test if a pattern matches, then you want to use `pcase` > or `pcase-exhaustive`, and not `pcase-let`. > > If you want a "one-branch `pcase-exhaustive` with a let-style notation", > we could add such a thing of course, but I'd first like to see some > evidence that it's useful in practice. > > > Stefan > > -- Marco Antoniotti Somewhere over the Rainbow [-- Attachment #2: Type: text/html, Size: 2610 bytes --] ^ permalink raw reply [flat|nested] 18+ messages in thread
* bug#70597: Problem in pcase-let? 2024-04-28 15:38 ` Marco Antoniotti @ 2024-04-28 17:05 ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors 2024-04-28 18:22 ` Marco Antoniotti 0 siblings, 1 reply; 18+ messages in thread From: Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors @ 2024-04-28 17:05 UTC (permalink / raw) To: Marco Antoniotti; +Cc: Bruno Barbier, 70597 > Let me just answer the destructuring-bind comment by Stefan (I am answering > to his last email). The previous ones are somewhat answered here as well. > > In some sense, yes. I kind of want destructuring-bind. It is, IMHO, > unfortunate that ELisp does not have it and that we don't have > cl-destructuring-bind either; lower level beast than matching, but useful. I don't understand what you mean: `pcase-let` *is* a destructring bind, and we also do have `cl-destructuring-bind`. > As per the pcase-let, I still think that the name and/or its behavior > are confusing because of expectations about how a pattern matcher > usually works. Yes, clearly there is a problem of users being surprised. But AFAICT, changing the semantics is not the right answer, because the current behavior matches(!) what is usually needed and because the other behaviors are already well-served by `pcase` and `pcase-exhaustive`. Maybe a better answer is to try and detect ill-conceived patterns like in: (pcase-let (`(foo bar ,x) (SOMETHING)) (ANYTHING)) and emit a warning suggesting to rewrite it to (pcase-let (`(,_ ,_ ,x) (SOMETHING)) (ANYTHING)) - Stefan ^ permalink raw reply [flat|nested] 18+ messages in thread
* bug#70597: Problem in pcase-let? 2024-04-28 17:05 ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors @ 2024-04-28 18:22 ` Marco Antoniotti 2024-04-28 21:08 ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors 0 siblings, 1 reply; 18+ messages in thread From: Marco Antoniotti @ 2024-04-28 18:22 UTC (permalink / raw) To: Stefan Monnier; +Cc: Bruno Barbier, 70597 [-- Attachment #1: Type: text/plain, Size: 1726 bytes --] Hi oooops sorry. Somehow I was missing cl-destructuring-bind; my bad. In any case, at a minimum the warning should be issued. I did refrain from using pcase-let after all, although it "seemed right" for my use case. Having said that, I would advocate changing the semantics. Your call anyway. All the best On Sun, Apr 28, 2024 at 7:05 PM Stefan Monnier <monnier@iro.umontreal.ca> wrote: > > Let me just answer the destructuring-bind comment by Stefan (I am > answering > > to his last email). The previous ones are somewhat answered here as > well. > > > > In some sense, yes. I kind of want destructuring-bind. It is, IMHO, > > unfortunate that ELisp does not have it and that we don't have > > cl-destructuring-bind either; lower level beast than matching, but > useful. > > I don't understand what you mean: `pcase-let` *is* a destructring bind, > and we also do have `cl-destructuring-bind`. > > > As per the pcase-let, I still think that the name and/or its behavior > > are confusing because of expectations about how a pattern matcher > > usually works. > > Yes, clearly there is a problem of users being surprised. > > But AFAICT, changing the semantics is not the right answer, because the > current behavior matches(!) what is usually needed and because the other > behaviors are already well-served by `pcase` and `pcase-exhaustive`. > > Maybe a better answer is to try and detect ill-conceived patterns like in: > > (pcase-let (`(foo bar ,x) (SOMETHING)) (ANYTHING)) > > and emit a warning suggesting to rewrite it to > > (pcase-let (`(,_ ,_ ,x) (SOMETHING)) (ANYTHING)) > > > - Stefan > > -- Marco Antoniotti Somewhere over the Rainbow [-- Attachment #2: Type: text/html, Size: 2419 bytes --] ^ permalink raw reply [flat|nested] 18+ messages in thread
* bug#70597: Problem in pcase-let? 2024-04-28 18:22 ` Marco Antoniotti @ 2024-04-28 21:08 ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors 2024-05-02 9:23 ` Eli Zaretskii 2024-05-04 15:23 ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors 0 siblings, 2 replies; 18+ messages in thread From: Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors @ 2024-04-28 21:08 UTC (permalink / raw) To: Marco Antoniotti; +Cc: Bruno Barbier, 70597 > In any case, at a minimum the warning should be issued. I haven't looked at the code for it, so I don't know how easy it is to implement, but let' hope there's an "easy" way to do it. > I did refrain from using pcase-let after all, although it "seemed > right" for my use case. Having said that, I would advocate changing > the semantics. The places that already use it largely rely on the current semantics, so changing it would introduce a lot of breakage. It's not really an option. Stefan ^ permalink raw reply [flat|nested] 18+ messages in thread
* bug#70597: Problem in pcase-let? 2024-04-28 21:08 ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors @ 2024-05-02 9:23 ` Eli Zaretskii 2024-05-02 11:06 ` Marco Antoniotti 2024-05-04 15:23 ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors 1 sibling, 1 reply; 18+ messages in thread From: Eli Zaretskii @ 2024-05-02 9:23 UTC (permalink / raw) To: Stefan Monnier; +Cc: brubar.cs, marcoxa, 70597 > Cc: Bruno Barbier <brubar.cs@gmail.com>, 70597@debbugs.gnu.org > Date: Sun, 28 Apr 2024 17:08:21 -0400 > From: Stefan Monnier via "Bug reports for GNU Emacs, > the Swiss army knife of text editors" <bug-gnu-emacs@gnu.org> > > > In any case, at a minimum the warning should be issued. > > I haven't looked at the code for it, so I don't know how easy it is to > implement, but let' hope there's an "easy" way to do it. > > > I did refrain from using pcase-let after all, although it "seemed > > right" for my use case. Having said that, I would advocate changing > > the semantics. > > The places that already use it largely rely on the current semantics, > so changing it would introduce a lot of breakage. > It's not really an option. So I guess we should close this as wontfix? ^ permalink raw reply [flat|nested] 18+ messages in thread
* bug#70597: Problem in pcase-let? 2024-05-02 9:23 ` Eli Zaretskii @ 2024-05-02 11:06 ` Marco Antoniotti 2024-05-04 11:35 ` Eli Zaretskii 0 siblings, 1 reply; 18+ messages in thread From: Marco Antoniotti @ 2024-05-02 11:06 UTC (permalink / raw) To: Eli Zaretskii; +Cc: brubar.cs, Stefan Monnier, 70597 [-- Attachment #1: Type: text/plain, Size: 1281 bytes --] Hi guys, it's your call. But please change the doc string to clarify that pcase-let does not do "symbol equality" pattern matching, but only structural matching. Adding an example like the following will help. (pcase-let ((`(foo ,x 23 ,y) '(bar 11 baz 22))) (list x y)) All the best Marco On Thu, May 2, 2024 at 11:24 AM Eli Zaretskii <eliz@gnu.org> wrote: > > Cc: Bruno Barbier <brubar.cs@gmail.com>, 70597@debbugs.gnu.org > > Date: Sun, 28 Apr 2024 17:08:21 -0400 > > From: Stefan Monnier via "Bug reports for GNU Emacs, > > the Swiss army knife of text editors" <bug-gnu-emacs@gnu.org> > > > > > In any case, at a minimum the warning should be issued. > > > > I haven't looked at the code for it, so I don't know how easy it is to > > implement, but let' hope there's an "easy" way to do it. > > > > > I did refrain from using pcase-let after all, although it "seemed > > > right" for my use case. Having said that, I would advocate changing > > > the semantics. > > > > The places that already use it largely rely on the current semantics, > > so changing it would introduce a lot of breakage. > > It's not really an option. > > So I guess we should close this as wontfix? > -- Marco Antoniotti Somewhere over the Rainbow [-- Attachment #2: Type: text/html, Size: 2224 bytes --] ^ permalink raw reply [flat|nested] 18+ messages in thread
* bug#70597: Problem in pcase-let? 2024-05-02 11:06 ` Marco Antoniotti @ 2024-05-04 11:35 ` Eli Zaretskii 2024-05-04 12:06 ` Marco Antoniotti 0 siblings, 1 reply; 18+ messages in thread From: Eli Zaretskii @ 2024-05-04 11:35 UTC (permalink / raw) To: Marco Antoniotti; +Cc: brubar.cs, monnier, 70597-done > From: Marco Antoniotti <marcoxa@gmail.com> > Date: Thu, 2 May 2024 13:06:58 +0200 > Cc: Stefan Monnier <monnier@iro.umontreal.ca>, brubar.cs@gmail.com, 70597@debbugs.gnu.org > > it's your call. But please change the doc string to clarify that pcase-let does not do "symbol equality" pattern > matching, but only structural matching. Adding an example like the following will help. > > (pcase-let ((`(foo ,x 23 ,y) '(bar 11 baz 22))) (list x y)) This is already explained in the ELisp manual, and the doc string already says Each EXP should match its respective PATTERN (i.e. be of structure compatible to PATTERN) So I don't think we need to do anything else here, and I'm closing this bug. ^ permalink raw reply [flat|nested] 18+ messages in thread
* bug#70597: Problem in pcase-let? 2024-05-04 11:35 ` Eli Zaretskii @ 2024-05-04 12:06 ` Marco Antoniotti 2024-05-04 15:05 ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors 0 siblings, 1 reply; 18+ messages in thread From: Marco Antoniotti @ 2024-05-04 12:06 UTC (permalink / raw) To: Eli Zaretskii; +Cc: brubar.cs, monnier, 70597-done [-- Attachment #1: Type: text/plain, Size: 1140 bytes --] Hi sorry, but I do not think that the current doc string and/or the manual explains the situation. And it looks like this is a recurring misunderstanding by the users. Just adding the example would clarify things. All the best MA On Sat, May 4, 2024 at 1:35 PM Eli Zaretskii <eliz@gnu.org> wrote: > > From: Marco Antoniotti <marcoxa@gmail.com> > > Date: Thu, 2 May 2024 13:06:58 +0200 > > Cc: Stefan Monnier <monnier@iro.umontreal.ca>, brubar.cs@gmail.com, > 70597@debbugs.gnu.org > > > > it's your call. But please change the doc string to clarify that > pcase-let does not do "symbol equality" pattern > > matching, but only structural matching. Adding an example like the > following will help. > > > > (pcase-let ((`(foo ,x 23 ,y) '(bar 11 baz 22))) (list x y)) > > This is already explained in the ELisp manual, and the doc string > already says > > Each EXP should match its respective PATTERN (i.e. be of structure > compatible to PATTERN) > > So I don't think we need to do anything else here, and I'm closing > this bug. > -- Marco Antoniotti Somewhere over the Rainbow [-- Attachment #2: Type: text/html, Size: 1960 bytes --] ^ permalink raw reply [flat|nested] 18+ messages in thread
* bug#70597: Problem in pcase-let? 2024-05-04 12:06 ` Marco Antoniotti @ 2024-05-04 15:05 ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors 2024-05-05 8:49 ` Marco Antoniotti 0 siblings, 1 reply; 18+ messages in thread From: Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors @ 2024-05-04 15:05 UTC (permalink / raw) To: Marco Antoniotti; +Cc: brubar.cs, Eli Zaretskii, 70597-done > sorry, but I do not think that the current doc string and/or the > manual explains the situation. Which "current" are you referring to? The "current" manual (in `master`) has a whole section on "Destructuring with pcase pattern" (see below). Do you still see room for misunderstanding there? If so, can you suggest how to change it to make it more clear? Stefan @node Destructuring with pcase Patterns @subsection Destructuring with @code{pcase} Patterns @cindex 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. 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 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{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}. Extraction of multiple values stored in an object is known as @dfn{destructuring}. Using @code{pcase} patterns allows you to perform @dfn{destructuring 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 @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) 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{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 @ref{seq-let}. @defmac pcase-let bindings body@dots{} Perform destructuring binding of variables according to @var{bindings}, and then evaluate @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 @code{pcase} pattern. All @var{exp}s are evaluated first, after which they are matched against their respective @var{pattern}, introducing new variable bindings that can then be used inside @var{body}. 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}. Here's a trivial example: @example (pcase-let ((`(,major ,minor) (split-string "image/png" "/"))) minor) @result{} "png" @end example @end defmac @defmac pcase-let* bindings body@dots{} Perform destructuring binding of variables according to @var{bindings}, 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 @var{pattern} 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 @var{exp}s of the @var{bindings} that follow it, additionally to being available in @var{body}. @end defmac @defmac pcase-dolist (pattern list) body@dots{} Execute @var{body} once for each element of @var{list}, on each iteration performing a destructuring binding of variables in @var{pattern} to the values of the corresponding subfields of the element of @var{list}. The bindings are performed as if by @code{pcase-let}. When @var{pattern} is a simple variable, this ends up being equivalent to @code{dolist} (@pxref{Iteration}). @end defmac @defmac pcase-setq pattern value@dots{} Assign values to variables in a @code{setq} form, destructuring each @var{value} according to its respective @var{pattern}. @end defmac @defmac pcase-lambda lambda-list &rest body This is like @code{lambda}, but allows each argument to be a pattern. For instance, here's a simple function that takes a cons cell as the argument: @example (setq fun (pcase-lambda (`(,key . ,val)) (vector key (* val 10)))) (funcall fun '(foo . 2)) @result{} [foo 20] @end example @end defmac ^ permalink raw reply [flat|nested] 18+ messages in thread
* bug#70597: Problem in pcase-let? 2024-05-04 15:05 ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors @ 2024-05-05 8:49 ` Marco Antoniotti 0 siblings, 0 replies; 18+ messages in thread From: Marco Antoniotti @ 2024-05-05 8:49 UTC (permalink / raw) To: Stefan Monnier; +Cc: brubar.cs, Eli Zaretskii, 70597-done [-- Attachment #1: Type: text/plain, Size: 6692 bytes --] Hi Stefan, i usually just to C-h f. This is what you get from it, in 29.3. 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 its respective PATTERN (i.e. be of structure compatible to PATTERN); a mismatch may signal an error or may go undetected, binding variables to arbitrary values, such as nil. Probably introduced at or before Emacs version 28.1. The Info doc you posted is definitively better. All the best MA On Sat, May 4, 2024 at 5:05 PM Stefan Monnier <monnier@iro.umontreal.ca> wrote: > > sorry, but I do not think that the current doc string and/or the > > manual explains the situation. > > Which "current" are you referring to? The "current" manual (in > `master`) has a whole section on "Destructuring with pcase pattern" > (see below). > > Do you still see room for misunderstanding there? > If so, can you suggest how to change it to make it more clear? > > > Stefan > > > @node Destructuring with pcase Patterns > @subsection Destructuring with @code{pcase} Patterns > @cindex 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. > 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 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{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}. > > Extraction of multiple values stored in an object is known as > @dfn{destructuring}. Using @code{pcase} patterns allows you to > perform @dfn{destructuring 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 @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) 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{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 > @ref{seq-let}. > > @defmac pcase-let bindings body@dots{} > Perform destructuring binding of variables according to > @var{bindings}, and then evaluate @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 @code{pcase} pattern. > > All @var{exp}s are evaluated first, after which they are matched > against their respective @var{pattern}, introducing new variable > bindings that can then be used inside @var{body}. 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}. > > Here's a trivial example: > > @example > (pcase-let ((`(,major ,minor) > (split-string "image/png" "/"))) > minor) > @result{} "png" > @end example > @end defmac > > @defmac pcase-let* bindings body@dots{} > Perform destructuring binding of variables according to > @var{bindings}, 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 > @var{pattern} 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 > @var{exp}s of the @var{bindings} that follow it, additionally to > being available in @var{body}. > @end defmac > > @defmac pcase-dolist (pattern list) body@dots{} > Execute @var{body} once for each element of @var{list}, on each > iteration performing a destructuring binding of variables in > @var{pattern} to the values of the corresponding subfields of the > element of @var{list}. The bindings are performed as if by > @code{pcase-let}. When @var{pattern} is a simple variable, this ends > up being equivalent to @code{dolist} (@pxref{Iteration}). > @end defmac > > @defmac pcase-setq pattern value@dots{} > Assign values to variables in a @code{setq} form, destructuring each > @var{value} according to its respective @var{pattern}. > @end defmac > > @defmac pcase-lambda lambda-list &rest body > This is like @code{lambda}, but allows each argument to be a pattern. > For instance, here's a simple function that takes a cons cell as the > argument: > > @example > (setq fun > (pcase-lambda (`(,key . ,val)) > (vector key (* val 10)))) > (funcall fun '(foo . 2)) > @result{} [foo 20] > @end example > @end defmac > > > -- Marco Antoniotti Somewhere over the Rainbow [-- Attachment #2: Type: text/html, Size: 8249 bytes --] ^ permalink raw reply [flat|nested] 18+ messages in thread
* bug#70597: Problem in pcase-let? 2024-04-28 21:08 ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors 2024-05-02 9:23 ` Eli Zaretskii @ 2024-05-04 15:23 ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors 1 sibling, 0 replies; 18+ messages in thread From: Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors @ 2024-05-04 15:23 UTC (permalink / raw) To: Marco Antoniotti; +Cc: Bruno Barbier, 70597 > I haven't looked at the code for it, so I don't know how easy it is to > implement, but let' hope there's an "easy" way to do it. Hmm... the patch below kind of works, but it's not ideal and it's not easy to fix its shortcomings: - It happens a bit "too late", i.e. at a level where the pattern has already been macro-expanded so the message may refer to a subpattern that's not readily present in the source code. [ I think we can live with this. ] - It applies to more situations than just `pcase-let`, and for some of them the warning is not desirable. - It has a few false positives. This last point is because of a fuzziness about what it is we want to warn about: in a pattern like `[a ,b] there are fundamentally 3 tests: - Is the pattern of type `vector`. - Does the vector have size 2. - Is the first element equal to `a`. We want to drop all three. But we don't want to warn about the first two, since there's no convenient way to write a pattern without them. But for some other patterns the equivalent to the first point above can look like `(equal (type-of foo) 'bar)` and thus ends up caught in our warning (which basically warns when we test that something is equal to some constant), even though there's no other way to write the pattern. Stefan diff --git a/lisp/emacs-lisp/pcase.el b/lisp/emacs-lisp/pcase.el index 23f1bac600c..f0302dbcbe0 100644 --- a/lisp/emacs-lisp/pcase.el +++ b/lisp/emacs-lisp/pcase.el @@ -1050,6 +1058,11 @@ pcase--u1 `((,nsym ,(pcase--funcall fun sym vars))) body)))) ((eq (car-safe upat) 'quote) + (when (and (length= rest 1) + (not (memq (cadr upat) '(nil _))) ;Too common. + (eq 'match (car-safe (caar rest))) + (eq 'pcase--dontcare (cddr (caar rest)))) + (message "Ignoring pattern %S, you might replace it with _" upat)) (pcase--mark-used sym) (let* ((val (cadr upat)) (splitrest (pcase--split-rest ^ permalink raw reply related [flat|nested] 18+ messages in thread
end of thread, other threads:[~2024-05-05 8:49 UTC | newest] Thread overview: 18+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2024-04-26 18:00 bug#70597: Problem in pcase-let? Marco Antoniotti 2024-04-27 16:11 ` Bruno Barbier 2024-04-27 22:28 ` Marco Antoniotti 2024-04-28 10:01 ` Bruno Barbier 2024-04-28 10:07 ` Ihor Radchenko 2024-04-28 10:18 ` Eli Zaretskii 2024-04-28 15:22 ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors 2024-04-28 15:38 ` Marco Antoniotti 2024-04-28 17:05 ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors 2024-04-28 18:22 ` Marco Antoniotti 2024-04-28 21:08 ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors 2024-05-02 9:23 ` Eli Zaretskii 2024-05-02 11:06 ` Marco Antoniotti 2024-05-04 11:35 ` Eli Zaretskii 2024-05-04 12:06 ` Marco Antoniotti 2024-05-04 15:05 ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors 2024-05-05 8:49 ` Marco Antoniotti 2024-05-04 15:23 ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors
Code repositories for project(s) associated with this public inbox https://git.savannah.gnu.org/cgit/emacs.git This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).