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

From: Bruno Barbier <[email-masked]>
Date: Sat, 27 Apr 2024 18:11:41 +0200

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