Subject: Re: bug#71503: 30.0.50; pcase-lambda (with "and" and "guard") does not work as expected

From: Philip Kaludercic <[email-masked]>
Date: Sun, 21 Jul 2024 11:17:05 +0000

Eli Zaretskii <[email-masked]> writes:

>> From: Philip Kaludercic <[email-masked]>
>> Cc: [email-masked],  [email-masked],  [email-masked]
>> Date: Sat, 20 Jul 2024 10:29:55 +0000
>> 
>> >> > > The difference is that pcase-lambda doesn't do case-distinction, but
>> >> > > just pattern matching/destruncting.  So if the pattern-matching fails,
>> >> > > then the variable is just not bound, instead of the entire expression
>> >> > > falling back to returning no value/nil.  I am guessing you wanted to
>> >> > > have something like Scheme's `case-lambda'[0]?  Or we could
>> >> > > clarify this
>> >> > > point in the docstring.
>> >> > 
>> >> > Would you mind suggesting a clarification for the doc string (and the
>> >> > ELisp manual as well)?
>> 
>> Sorry, I didn't realise you were pining me.  I was thinking of something
>> like
>> 
>> diff --git a/lisp/emacs-lisp/pcase.el b/lisp/emacs-lisp/pcase.el
>> index 5a7f3995311..f546ba34c7c 100644
>> --- a/lisp/emacs-lisp/pcase.el
>> +++ b/lisp/emacs-lisp/pcase.el
>> @@ -241,9 +241,10 @@ pcase-exhaustive
>>  ;;;###autoload
>>  (defmacro pcase-lambda (lambda-list &rest body)
>>    "Like `lambda' but allow each argument to be a pattern.
>> -I.e. accepts the usual &optional and &rest keywords, but every
>> -formal argument can be any pattern accepted by `pcase' (a mere
>> -variable name being but a special case of it)."
>> +I.e. accepts the usual &optional and &rest keywords, but every formal
>> +argument can be any pattern accepted by `pcase' (a mere variable name
>> +being but a special case of it).  Keep in mind that BODY is always
>> +evaluated, regardless of whether the argument-patterns match or not."
>>    (declare (doc-string 2) (indent defun)
>>             (debug (&define (&rest pcase-PAT) lambda-doc def-body)))
>>    (let* ((bindings ())
>> 
>> but now I notice that `pcase-let*' documents that all expressions should
>> match,
>> 
>>   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.
>> 
>> Since `pcase-lambda' inherits these semantics we would have to propagate
>> this promise -- or be more specific about what happens, e.g. binding
>> values to nil.
>
> Thanks.  If this still can be fixed by some documentation changes, I'd
> prefer to do that.

In that case I think it would be better to stick to a warning like the
one in `pcase-let*'..

Stefan Monnier <[email-masked]> writes:

[...]

> I tend to call "any pattern accepted by `pcase'" a "Pcase pattern".
> More importantly, we should refer to `pcase-let` rather than to
> `pcase` here and we should likely use the term "destructuring (binding)".

What do you think of:

diff --git a/lisp/emacs-lisp/pcase.el b/lisp/emacs-lisp/pcase.el
index 5a7f3995311..fd6b0c8db5c 100644
--- a/lisp/emacs-lisp/pcase.el
+++ b/lisp/emacs-lisp/pcase.el
@@ -241,9 +241,14 @@ pcase-exhaustive
 ;;;###autoload
 (defmacro pcase-lambda (lambda-list &rest body)
   "Like `lambda' but allow each argument to be a pattern.
-I.e. accepts the usual &optional and &rest keywords, but every
-formal argument can be any pattern accepted by `pcase' (a mere
-variable name being but a special case of it)."
+I.e. accepts the usual &optional and &rest keywords, but every formal
+argument can be any pattern destructed by `pcase-let' (a mere variable
+name being but a special case of it).
+
+Each argument should match its respective pattern in the parameter
+list (i.e. be of a compatible structure); a mismatch may signal an error
+or may go undetected, binding arguments to arbitrary values, such as
+nil."
   (declare (doc-string 2) (indent defun)
            (debug (&define (&rest pcase-PAT) lambda-doc def-body)))
   (let* ((bindings ())

>         Stefan

-- 
	Philip Kaludercic on peregrine