Subject: Re: bug#70597: Problem in pcase-let?

From: Marco Antoniotti <[email-masked]>
Date: Sun, 28 Apr 2024 00:28:41 +0200

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 <[email-masked]> 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