* 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-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
* 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
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).