all messages for Emacs-related lists mirrored at yhetil.org
 help / color / mirror / code / Atom feed
* Instead of pcase
@ 2023-11-16  3:04 Richard Stallman
  2023-11-16  7:37 ` Philip Kaludercic
                   ` (4 more replies)
  0 siblings, 5 replies; 342+ messages in thread
From: Richard Stallman @ 2023-11-16  3:04 UTC (permalink / raw)
  To: emacs-devel

[[[ To any NSA and FBI agents reading my email: please consider    ]]]
[[[ whether defending the US Constitution against all enemies,     ]]]
[[[ foreign or domestic, requires you to follow Snowden's example. ]]]

`pcase' is a big and unnecessary complication on Emacs Lisp.
I think its presence worse overall.

One can easily think of `pcase' as "just another feature", like each
of the thousands of other predefined functions and macros in Emacs
Lisp.  But that picture is incorrect for `pcase', because it does not
count the cost of `pcase' in complexity.

What makes `pcase' such a complication is that it introduces an
additional "little language" that duplicates the functionality of part
of Emacs Lisp.  Even worse, that little language is so concise it is
downright cryptic.

I can see why people want something along those lines.  Using `cond'
and `let' to do these jobs feels long-winded and cumbersome; they were
not designed to make this easy.  So we wish for something to make such
code more concise.

`pcase' does indeed make such code more concise, but it takes that
conciseness to an extreme by defining its own cryptic little language,
That is going too far.

Using `pcase' in your own private code concerns you alone.  Using it
in released packages that others use but others rarely change or study
is not a big deal for the community.  However, putting `pcase' into
many packages imposes this cryptic little language on all of us.

There are other little languages in Emacs, but most of them are
limited to special high-level purposes -- which means that hardly any
of us need even be aware of them.

For instance, there is a little language called "quail" which is used
for concisely defining input methods.  Its specific purpose is a
high-level purpose.  If you don't work on input methods you never need
to learn quail.

It's just the opposite for `pcase' -- its specific purpose is a
low-level purpose, so it could appear in any part of the code of
Emacs, The burden of its complexity can fall on any or all of us.

Those of you who are fans of `pcase' may not recognize the cost it
imposes on the Emacs Lisp language.  You paid that cost already,
perhaps a few years ago, and perhaps you enjoy each new language
construct you learn.  Perhaps, for you, the more complexity of
features to be learned, the better.

But don't argue that this cost does not exist, simply because it
doesn't feel like a burden to you.

So...

I'm looking at adapting some of the features of `pcase' into other
constructs, so as to make type-discrimination code more concise than
in old-fashioned Lisp, but _not_ so concise as to be cryptic and
burdensome.

-- 
Dr Richard Stallman (https://stallman.org)
Chief GNUisance of the GNU Project (https://gnu.org)
Founder, Free Software Foundation (https://fsf.org)
Internet Hall-of-Famer (https://internethalloffame.org)





^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: Instead of pcase
  2023-11-16  3:04 Instead of pcase Richard Stallman
@ 2023-11-16  7:37 ` Philip Kaludercic
  2023-11-16 17:18   ` T.V Raman
  2023-11-26  3:17   ` Richard Stallman
  2023-11-16 15:06 ` Michael Heerdegen
                   ` (3 subsequent siblings)
  4 siblings, 2 replies; 342+ messages in thread
From: Philip Kaludercic @ 2023-11-16  7:37 UTC (permalink / raw)
  To: Richard Stallman; +Cc: emacs-devel

Richard Stallman <rms@gnu.org> writes:

> I can see why people want something along those lines.  Using `cond'
> and `let' to do these jobs feels long-winded and cumbersome; they were
> not designed to make this easy.  So we wish for something to make such
> code more concise.

[...]

> I'm looking at adapting some of the features of `pcase' into other
> constructs, so as to make type-discrimination code more concise than
> in old-fashioned Lisp, but _not_ so concise as to be cryptic and
> burdensome.

The critical feature of pcase is pattern matching.  The complexity of
`pcase' is the extensibility -- a lisp-like flexibility that makes it so
attractive -- that a simpler macro might not need.  The question is, if
one would restrict pcase to just matching expressions using ` and , like

  (pcase sexp ;match various top-level constructs
    (`(defun ,name ,args ,body) ...)
    (`(defvar ,name, ,value) ...)
    (`(require ',symbol) ...)
    ...)

would that be simple enough in your opinion?  Anyone familiar with
ML-style functional programming, Prolog or the notion of unification
should be able to understand this quickly enough, I assume?



^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: Instead of pcase
  2023-11-16  3:04 Instead of pcase Richard Stallman
  2023-11-16  7:37 ` Philip Kaludercic
@ 2023-11-16 15:06 ` Michael Heerdegen
  2023-11-16 17:31   ` T.V Raman
  2023-11-20  3:06   ` Richard Stallman
  2023-11-16 15:20 ` Spencer Baugh
                   ` (2 subsequent siblings)
  4 siblings, 2 replies; 342+ messages in thread
From: Michael Heerdegen @ 2023-11-16 15:06 UTC (permalink / raw)
  To: emacs-devel

Richard Stallman <rms@gnu.org> writes:

> What makes `pcase' such a complication is that it introduces an
> additional "little language" that duplicates the functionality of part
> of Emacs Lisp.  Even worse, that little language is so concise it is
> downright cryptic.

It is not cryptic per se.  People are sometimes frightened by the
syntax, for some it seems to be hard to learn and understand, I don't
know why, but I accept that as a fact.

> Those of you who are fans of `pcase' may not recognize the cost it
> imposes on the Emacs Lisp language.  You paid that cost already,
> perhaps a few years ago, and perhaps you enjoy each new language
> construct you learn.  Perhaps, for you, the more complexity of
> features to be learned, the better.
>
> But don't argue that this cost does not exist, simply because it
> doesn't feel like a burden to you.

Hmm, I must say that cost was small for me.  There is also a cost of
reading a more complicated rewrite using less suited language
constructs.  And i have to pay the price each time I need to read the
more complicated rewrite, instead of only once.

> I'm looking at adapting some of the features of `pcase' into other
> constructs, so as to make type-discrimination code more concise than
> in old-fashioned Lisp, but _not_ so concise as to be cryptic and
> burdensome.

I wonder how that would look like and if it would really be simpler.  Or
if it would be structurally more or less equivalent and only avoid the
concise syntax.

Because, we need different semantic features, and we want that it's
possible for them to be combined.  I think we would more or less end
either with `pattern-case' that is like pcase but more verbose, or with
something that is simpler, but when some requirement in the code
changes, like a destructering having to be made conditional, has to be
rewritten to use a more complicated construct, or plain Elisp.


Michael.




^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: Instead of pcase
  2023-11-16  3:04 Instead of pcase Richard Stallman
  2023-11-16  7:37 ` Philip Kaludercic
  2023-11-16 15:06 ` Michael Heerdegen
@ 2023-11-16 15:20 ` Spencer Baugh
  2023-11-16 20:16   ` Tomas Hlavaty
  2023-11-18  3:03   ` combining cond and let, to replace pcase Richard Stallman
  2023-11-16 18:11 ` Instead of pcase Emanuel Berg
  2023-11-16 18:22 ` Jim Porter
  4 siblings, 2 replies; 342+ messages in thread
From: Spencer Baugh @ 2023-11-16 15:20 UTC (permalink / raw)
  To: emacs-devel


Setting aside whether pcase is good or not:

I've thought before that it would be nice to have a cond-let construct,
like if-let and when-let.  The body of a cond clause would be bound to
the result of the condition.  Perhaps that could be a good alternative
to some use-cases for pcase?

For example, if one has a cons whose cdr is a string if the car is 'foo,
and whose cdr is a number if the car is 'bar, then with pcase one can
write:

(let ((exp (if t '(foo . "str") '(bar . 7))))
  (pcase exp
    (`(foo . ,val) (concat "str" val))
    (`(bar . ,val) (+ 1 val))))

and with cond-let one could write:

(let ((exp (if t '(foo . "str") '(bar . 7))))
  (cond-let
   ((val
     (and (eq (car exp) 'foo) (cdr exp)))
    (concat "str" val))
   ((val
     (and (eq (car exp) 'bar) (cdr exp)))
    (+ 1 val))))

Which is maybe nicer?




^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: Instead of pcase
  2023-11-16  7:37 ` Philip Kaludercic
@ 2023-11-16 17:18   ` T.V Raman
  2023-11-16 17:44     ` Michael Heerdegen
                       ` (2 more replies)
  2023-11-26  3:17   ` Richard Stallman
  1 sibling, 3 replies; 342+ messages in thread
From: T.V Raman @ 2023-11-16 17:18 UTC (permalink / raw)
  To: Philip Kaludercic; +Cc: Richard Stallman, emacs-devel

Philip Kaludercic <philipk@posteo.net> writes:


RMS' message makes some very valuable points re specialized languages
like pcase -- pcase has its strengths, but in general, it's definitely
not easy to understand complex code that leverages it -- as an example:

I recently tried to understand some of the completion code; --
specifically, completion-at-point, and immediately hit the pcase wall
and gave up --- my lack of understanding of pcase made that code in
Emacs Core read like line-noise.
> Richard Stallman <rms@gnu.org> writes:
>
>> I can see why people want something along those lines.  Using `cond'
>> and `let' to do these jobs feels long-winded and cumbersome; they were
>> not designed to make this easy.  So we wish for something to make such
>> code more concise.
>
> [...]
>
>> I'm looking at adapting some of the features of `pcase' into other
>> constructs, so as to make type-discrimination code more concise than
>> in old-fashioned Lisp, but _not_ so concise as to be cryptic and
>> burdensome.
>
> The critical feature of pcase is pattern matching.  The complexity of
> `pcase' is the extensibility -- a lisp-like flexibility that makes it so
> attractive -- that a simpler macro might not need.  The question is, if
> one would restrict pcase to just matching expressions using ` and , like
>
>   (pcase sexp ;match various top-level constructs
>     (`(defun ,name ,args ,body) ...)
>     (`(defvar ,name, ,value) ...)
>     (`(require ',symbol) ...)
>     ...)
>
> would that be simple enough in your opinion?  Anyone familiar with
> ML-style functional programming, Prolog or the notion of unification
> should be able to understand this quickly enough, I assume?
>

-- 



^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: Instead of pcase
  2023-11-16 15:06 ` Michael Heerdegen
@ 2023-11-16 17:31   ` T.V Raman
  2023-11-16 18:26     ` Jim Porter
  2023-11-20  3:06   ` Richard Stallman
  1 sibling, 1 reply; 342+ messages in thread
From: T.V Raman @ 2023-11-16 17:31 UTC (permalink / raw)
  To: Michael Heerdegen; +Cc: emacs-devel

Michael Heerdegen <michael_heerdegen@web.de> writes:

See my other response re pcase and its use in emacs core; specifically
completion-at-point. A good compromize might be for the pcase fan who
wrote that code to explain its use just before the function with some
comments; that would actually help someone looking at the code to
understand it, and perhaps even turn a pcase sceptic into a pcase fan.

> Richard Stallman <rms@gnu.org> writes:
>
>> What makes `pcase' such a complication is that it introduces an
>> additional "little language" that duplicates the functionality of part
>> of Emacs Lisp.  Even worse, that little language is so concise it is
>> downright cryptic.
>
> It is not cryptic per se.  People are sometimes frightened by the
> syntax, for some it seems to be hard to learn and understand, I don't
> know why, but I accept that as a fact.
>
>> Those of you who are fans of `pcase' may not recognize the cost it
>> imposes on the Emacs Lisp language.  You paid that cost already,
>> perhaps a few years ago, and perhaps you enjoy each new language
>> construct you learn.  Perhaps, for you, the more complexity of
>> features to be learned, the better.
>>
>> But don't argue that this cost does not exist, simply because it
>> doesn't feel like a burden to you.
>
> Hmm, I must say that cost was small for me.  There is also a cost of
> reading a more complicated rewrite using less suited language
> constructs.  And i have to pay the price each time I need to read the
> more complicated rewrite, instead of only once.
>
>> I'm looking at adapting some of the features of `pcase' into other
>> constructs, so as to make type-discrimination code more concise than
>> in old-fashioned Lisp, but _not_ so concise as to be cryptic and
>> burdensome.
>
> I wonder how that would look like and if it would really be simpler.  Or
> if it would be structurally more or less equivalent and only avoid the
> concise syntax.
>
> Because, we need different semantic features, and we want that it's
> possible for them to be combined.  I think we would more or less end
> either with `pattern-case' that is like pcase but more verbose, or with
> something that is simpler, but when some requirement in the code
> changes, like a destructering having to be made conditional, has to be
> rewritten to use a more complicated construct, or plain Elisp.
>
>
> Michael.
>
>

-- 



^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: Instead of pcase
  2023-11-16 17:18   ` T.V Raman
@ 2023-11-16 17:44     ` Michael Heerdegen
  2023-11-16 18:16       ` Philip Kaludercic
  2023-11-16 19:19       ` Instead of pcase Eli Zaretskii
  2023-11-16 18:21     ` Dmitry Gutov
  2023-11-16 23:41     ` Emanuel Berg
  2 siblings, 2 replies; 342+ messages in thread
From: Michael Heerdegen @ 2023-11-16 17:44 UTC (permalink / raw)
  To: emacs-devel

"T.V Raman" <raman@google.com> writes:

> I recently tried to understand some of the completion code; --
> specifically, completion-at-point, and immediately hit the pcase wall
> and gave up --- my lack of understanding of pcase made that code in
> Emacs Core read like line-noise.

But that pcase form is only performing trivial destructuring.  Only
that, nothing more.  If you can read backquote expressions, you can read
that with exactly the same ease.

Michael.




^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: Instead of pcase
  2023-11-16  3:04 Instead of pcase Richard Stallman
                   ` (2 preceding siblings ...)
  2023-11-16 15:20 ` Spencer Baugh
@ 2023-11-16 18:11 ` Emanuel Berg
  2023-11-16 19:26   ` Eli Zaretskii
  2023-11-16 18:22 ` Jim Porter
  4 siblings, 1 reply; 342+ messages in thread
From: Emanuel Berg @ 2023-11-16 18:11 UTC (permalink / raw)
  To: emacs-devel

Richard Stallman wrote:

> `pcase' is a big and unnecessary complication on Emacs Lisp.
> I think its presence worse overall.
>
> One can easily think of `pcase' as "just another feature",
> like each of the thousands of other predefined functions and
> macros in Emacs Lisp. But that picture is incorrect for
> `pcase', because it does not count the cost of `pcase'
> in complexity.

There are, according to the below code [last], 13 011 hits for
cl-lib in the Emacs source. For pcase, there are 2168.
So there is no kicking that out either. But regardless of
whatever, here is the use of pcase,

   1525 pcase
    189 pcase-let
    137 pcase-dolist
     95 pcase-let*
     43 pcase-lambda
     35 pcase-exhaustive
     27 pcase-defmacro
     26 pcase-tests
     20 pcase-setq
     19 pcase-macroexpander
     10 pcase-vars
      7 pcase-patterns
      6 pcase-expand
      5 pcase-transform
      5 pcase-mutually
      4 pcase-bindings
      3 pcase-memoize
      3 pcase-compile
      2 pcase-used
      2 pcase-slot
      2 pcase-map
      1 pcase-matches
      1 pcase-default
      1 pcase-bug
Total: 2168

> Those of you who are fans of `pcase' may not recognize the
> cost it imposes on the Emacs Lisp language. You paid that
> cost already, perhaps a few years ago, and perhaps you enjoy
> each new language construct you learn. Perhaps, for you, the
> more complexity of features to be learned, the better.

Yes, I think a lot of people will say pcase is interesting.
But a lot of people will say it is very useful as well, and
they will disagree it places any kind of burden on anything.

In the case of pcase actually, with its pattern matching
feature, I think a lot of people will say, if anything, it
makes the code more light.

#! /bin/zsh
#
# this file:
#   https://dataswamp.org/~incal/conf/.zsh/emacs

clp () {
    cd ~/src/emacs
    local re='pcase|pcase-[a-z0-9*]+'
    grep -E -h -o -w  $re **/*.el | sort | uniq -c | sort -b -n -r
    echo 'Total:' $(grep -E -h -o -w $re **/*.el | wc -l)
}

cle () {
    cd ~/src/emacs
    local re='cl-[a-z0-9*]+'
    grep -E -h -o -w $re **/*.el | sort | uniq -c | sort -b -n -r | head -n 100
    echo 'Total:' $(grep -E -h -o -w $re **/*.el | wc -l)
}

GNU Emacs 30.0.50 (build 1, x86_64-pc-linux-gnu, cairo version
1.16.0) of 2023-11-01 [commit
8eb9b82ce58a8323af21f52625a401e19e279a9c]

-- 
underground experts united
https://dataswamp.org/~incal




^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: Instead of pcase
  2023-11-16 17:44     ` Michael Heerdegen
@ 2023-11-16 18:16       ` Philip Kaludercic
  2023-11-17  8:54         ` Complex SPEC for variables/customization like font-lock-keywords/org-capture-templates/etc (was: Instead of pcase) Ihor Radchenko
  2023-11-16 19:19       ` Instead of pcase Eli Zaretskii
  1 sibling, 1 reply; 342+ messages in thread
From: Philip Kaludercic @ 2023-11-16 18:16 UTC (permalink / raw)
  To: Michael Heerdegen; +Cc: emacs-devel

Michael Heerdegen <michael_heerdegen@web.de> writes:

> "T.V Raman" <raman@google.com> writes:
>
>> I recently tried to understand some of the completion code; --
>> specifically, completion-at-point, and immediately hit the pcase wall
>> and gave up --- my lack of understanding of pcase made that code in
>> Emacs Core read like line-noise.
>
> But that pcase form is only performing trivial destructuring.  Only
> that, nothing more.  If you can read backquote expressions, you can read
> that with exactly the same ease.

Right, and if one wouldn't use it to destruct values, you'd end up with
a lot more boiler-plate code that would be harder to maintain and more
to read.  If one has to talk about difficult to understand/remember
domain specific languages, then `font-lock-defaults' would be a much
more pressing candidate.

> Michael.



^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: Instead of pcase
  2023-11-16 17:18   ` T.V Raman
  2023-11-16 17:44     ` Michael Heerdegen
@ 2023-11-16 18:21     ` Dmitry Gutov
  2023-11-16 18:39       ` T.V Raman
  2023-11-16 23:41     ` Emanuel Berg
  2 siblings, 1 reply; 342+ messages in thread
From: Dmitry Gutov @ 2023-11-16 18:21 UTC (permalink / raw)
  To: T.V Raman, Philip Kaludercic; +Cc: Richard Stallman, emacs-devel

On 16/11/2023 19:18, T.V Raman wrote:
> I recently tried to understand some of the completion code; --
> specifically, completion-at-point, and immediately hit the pcase wall
> and gave up --- my lack of understanding of pcase made that code in
> Emacs Core read like line-noise.

Is there a general pattern matching/destructuring syntax that you find 
easier to read, in any language?



^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: Instead of pcase
  2023-11-16  3:04 Instead of pcase Richard Stallman
                   ` (3 preceding siblings ...)
  2023-11-16 18:11 ` Instead of pcase Emanuel Berg
@ 2023-11-16 18:22 ` Jim Porter
  2023-11-16 22:55   ` Emanuel Berg
  2023-11-17  5:36   ` Po Lu
  4 siblings, 2 replies; 342+ messages in thread
From: Jim Porter @ 2023-11-16 18:22 UTC (permalink / raw)
  To: rms, emacs-devel

On 11/15/2023 7:04 PM, Richard Stallman wrote:
> Those of you who are fans of `pcase' may not recognize the cost it
> imposes on the Emacs Lisp language.  You paid that cost already,
> perhaps a few years ago, and perhaps you enjoy each new language
> construct you learn.  Perhaps, for you, the more complexity of
> features to be learned, the better.

I'd like to offer a slightly different perspective here, as someone who 
only fairly recently became comfortable with Lisp (of any variety). I've 
used Emacs for a long time, but I found Lisp completely incomprehensible 
until just a couple of years ago. While getting started with Lisp isn't 
terribly complex, it's still quite a bit to learn, and it took a period 
where I was between jobs before I could dedicate the time I needed to 
get comfortable with writing Lisp.

I encountered a lot of hurdles with Lisp along the way. The first one 
was extremely basic: I needed to get used to the style of indentation 
and develop an intuition for *reading* Lisp code, rather than slowly and 
laboriously translating it into a form I could understand more easily.

The next hurdle was quoting. I still remember that one of my first 
patches to Emacs needed someone else to fix it in a followup because I 
messed up the quoting. The issues of quoting came up repeatedly for me 
as I encountered progressively more complex examples of quoting.

This is where we get to 'pcase'. I'll agree that the upper limit on 
complex quoted forms in 'pcase' is very high. I've used 'pcase-defmacro' 
in one nontrivial case, and I found it very difficult to get right.

*However*, 99% of the 'pcase' instances I've written or encountered are 
pretty simple for me to understand. Once I learned about 'pred' matcher 
and how to destructure via backquote patterns, it was mostly smooth 
sailing for me.

Now, while I'd certainly say that I enjoy learning overall (or else I 
likely wouldn't have learned Lisp in the first place), I don't consider 
the complexity of a feature to be a positive. Instead, I prefer features 
that give me more power or better expressiveness. Often, that 
expressiveness comes at the cost of complexity under the hood (e.g. 
'pcase-defmacro'), but that's not a positive to me in and of itself.

Overall, 'pcase' is one of the parts of Elisp that I appreciate the 
most. Learning the basics of its mini-language took just a bit of 
reading. In addition to the docs, seeing examples helped: the first few 
times were a bit tricky to read, but I could usually understand what was 
happening, even if I couldn't (at the time) write my own 'pcase' code 
that worked. However, once I got the basics down, I quickly saw the 
benefits: I could combine a handful of basic tools to do bigger things, 
meaning I only need to know a small set of facts before I can tackle a 
complex task. This, to me, is the mark of a good language feature: I can 
compose it in ways that *multiply* the power of each (small, easy) bit.

At a higher level, I'd say it's worth considering the audience we want 
to focus on. For veteran (Emacs) Lisp programmers, new additions like 
'pcase' can increase the difficulty of reading new Elisp code: your 
prior mastery of the language isn't any good when you hit that "(pcase". 
However, many programmers today don't know Lisp, of any variety. For 
people like that, learning to contribute to Emacs means learning from 
the very beginning. Having gone through this, most of 'pcase' was very 
easy for me to pick up, and other parts of Elisp were much more 
challenging (it took me a long time to get comfortable with writing 
macros, which is also probably one of the reasons I found 
'pcase-defmacro' to be so tricky).

That said, it's true that every feature we add to Elisp increases the 
overall complexity because now there are more things to learn. However, 
in my opinion, the expressiveness of 'pcase' far outweighs this cost.



^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: Instead of pcase
  2023-11-16 17:31   ` T.V Raman
@ 2023-11-16 18:26     ` Jim Porter
  2023-11-16 18:40       ` T.V Raman
  0 siblings, 1 reply; 342+ messages in thread
From: Jim Porter @ 2023-11-16 18:26 UTC (permalink / raw)
  To: T.V Raman, Michael Heerdegen; +Cc: emacs-devel

On 11/16/2023 9:31 AM, T.V Raman wrote:
> See my other response re pcase and its use in emacs core; specifically
> completion-at-point. A good compromize might be for the pcase fan who
> wrote that code to explain its use just before the function with some
> comments; that would actually help someone looking at the code to
> understand it, and perhaps even turn a pcase sceptic into a pcase fan.

Just a thought... would you find a pcase shortdoc with lots of examples 
to be useful? I find I learn best from examples, and I think some 
well-annotated pcase examples could help demystify the syntax in an 
easier-to-digest way compared to the full manual. (The manual has a few 
examples already, but I think there's room for a lot more examples.)



^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: Instead of pcase
  2023-11-16 18:21     ` Dmitry Gutov
@ 2023-11-16 18:39       ` T.V Raman
  2023-11-16 18:47         ` Philip Kaludercic
  2023-11-16 18:49         ` Dmitry Gutov
  0 siblings, 2 replies; 342+ messages in thread
From: T.V Raman @ 2023-11-16 18:39 UTC (permalink / raw)
  To: dmitry; +Cc: raman, philipk, rms, emacs-devel

when-let let-alist etc have worked well for me.

What threw me with pcase is there are lots of special chars in that
particular example whose meaning I dont know, and looking those up and
understanding their use at the same time was what chased me away



Dmitry Gutov writes:
 > On 16/11/2023 19:18, T.V Raman wrote:
 > > I recently tried to understand some of the completion code; --
 > > specifically, completion-at-point, and immediately hit the pcase wall
 > > and gave up --- my lack of understanding of pcase made that code in
 > > Emacs Core read like line-noise.
 > 
 > Is there a general pattern matching/destructuring syntax that you find 
 > easier to read, in any language?

-- 



^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: Instead of pcase
  2023-11-16 18:26     ` Jim Porter
@ 2023-11-16 18:40       ` T.V Raman
  2023-11-16 19:13         ` Jim Porter
  0 siblings, 1 reply; 342+ messages in thread
From: T.V Raman @ 2023-11-16 18:40 UTC (permalink / raw)
  To: jporterbugs; +Cc: raman, michael_heerdegen, emacs-devel

Yes. especially if a use I was trying to understand had some helpful
guidance right next to it; that would also help one learn.


Jim Porter writes:
 > On 11/16/2023 9:31 AM, T.V Raman wrote:
 > > See my other response re pcase and its use in emacs core; specifically
 > > completion-at-point. A good compromize might be for the pcase fan who
 > > wrote that code to explain its use just before the function with some
 > > comments; that would actually help someone looking at the code to
 > > understand it, and perhaps even turn a pcase sceptic into a pcase fan.
 > 
 > Just a thought... would you find a pcase shortdoc with lots of examples 
 > to be useful? I find I learn best from examples, and I think some 
 > well-annotated pcase examples could help demystify the syntax in an 
 > easier-to-digest way compared to the full manual. (The manual has a few 
 > examples already, but I think there's room for a lot more examples.)

-- 



^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: Instead of pcase
  2023-11-16 18:39       ` T.V Raman
@ 2023-11-16 18:47         ` Philip Kaludercic
  2023-11-16 18:51           ` T.V Raman
  2023-11-18  3:04           ` Richard Stallman
  2023-11-16 18:49         ` Dmitry Gutov
  1 sibling, 2 replies; 342+ messages in thread
From: Philip Kaludercic @ 2023-11-16 18:47 UTC (permalink / raw)
  To: T.V Raman; +Cc: dmitry, rms, emacs-devel

"T.V Raman" <raman@google.com> writes:

> when-let let-alist etc have worked well for me.
>
> What threw me with pcase is there are lots of special chars in that
> particular example whose meaning I dont know, and looking those up and
> understanding their use at the same time was what chased me away

Taking the concrete example you mentioned, 

    (pcase res
      (`(,_ . ,(and (pred functionp) f)) (funcall f))
      (`(,hookfun . (,start ,end ,collection . ,plist))

the unknown or unfamiliar characters are "`" and ",".  The (dynamic)
pcase documentation string is pretty straightforward in explaining what
it does, or can you recall what confused you?:

--8<---------------cut here---------------start------------->8---
-- `QPAT

Backquote-style pcase patterns: `QPAT
QPAT can take the following forms:
  (QPAT1 . QPAT2)       matches if QPAT1 matches the car and QPAT2 the cdr.
  [QPAT1 QPAT2..QPATn]  matches a vector of length n and QPAT1..QPATn match
                           its 0..(n-1)th elements, respectively.
  ,PAT                  matches if the ‘pcase’ pattern PAT matches.
  SYMBOL                matches if EXPVAL is ‘equal’ to SYMBOL.
  KEYWORD               likewise for KEYWORD.
  NUMBER                likewise for NUMBER.
  STRING                likewise for STRING.

The list or vector QPAT is a template.  The predicate formed
by a backquote-style pattern is a combination of those
formed by any sub-patterns, wrapped in a top-level condition:
EXPVAL must be "congruent" with the template.  For example:

  `(technical ,forum)
--8<---------------cut here---------------end--------------->8---

Or if you mean "_", then

--8<---------------cut here---------------start------------->8---
                  PATTERN can take one of the forms:

  _                matches anything.
--8<---------------cut here---------------end--------------->8---

which is familiar to people coming from functional languages, but even
Elisp uses underscores to denote unused variables.



^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: Instead of pcase
  2023-11-16 18:39       ` T.V Raman
  2023-11-16 18:47         ` Philip Kaludercic
@ 2023-11-16 18:49         ` Dmitry Gutov
  1 sibling, 0 replies; 342+ messages in thread
From: Dmitry Gutov @ 2023-11-16 18:49 UTC (permalink / raw)
  To: T.V Raman; +Cc: philipk, rms, emacs-devel

On 16/11/2023 20:39, T.V Raman wrote:
> when-let let-alist etc have worked well for me.

when-let is not destructuring. let-alias is very limited -- 
destructuring only for one type.

What I meant is there are similar constructs in functional languages 
like ML/Haskell which have also been available lately in 
Python/Ruby/Rust, that allow both matching and getting the data out in 
the same construct, accepting many or all data types available in the 
language.

pcase is an implementation of that idea. Perhaps it looks a bit cryptic, 
but I'm not sure what better syntax it would have in Lisp, while 
retaining the same capabilities.

> What threw me with pcase is there are lots of special chars in that
> particular example whose meaning I dont know, and looking those up and
> understanding their use at the same time was what chased me away

Perhaps (info "(elisp) pcase Macro") will help?



^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: Instead of pcase
  2023-11-16 18:47         ` Philip Kaludercic
@ 2023-11-16 18:51           ` T.V Raman
  2023-11-18  3:04           ` Richard Stallman
  1 sibling, 0 replies; 342+ messages in thread
From: T.V Raman @ 2023-11-16 18:51 UTC (permalink / raw)
  To: philipk; +Cc: raman, dmitry, rms, emacs-devel

I walked away after seeing what at the time of looking looked like
line-noise to me. Now, if debugging that function was my day job, I'd
have gone the next step in understanding and answering the question
you ask. But given that is not the case,  I just moved on.


Philip Kaludercic writes:
 > "T.V Raman" <raman@google.com> writes:
 > 
 > > when-let let-alist etc have worked well for me.
 > >
 > > What threw me with pcase is there are lots of special chars in that
 > > particular example whose meaning I dont know, and looking those up and
 > > understanding their use at the same time was what chased me away
 > 
 > Taking the concrete example you mentioned, 
 > 
 >     (pcase res
 >       (`(,_ . ,(and (pred functionp) f)) (funcall f))
 >       (`(,hookfun . (,start ,end ,collection . ,plist))
 > 
 > the unknown or unfamiliar characters are "`" and ",".  The (dynamic)
 > pcase documentation string is pretty straightforward in explaining what
 > it does, or can you recall what confused you?:
 > 
 > --8<---------------cut here---------------start------------->8---
 > -- `QPAT
 > 
 > Backquote-style pcase patterns: `QPAT
 > QPAT can take the following forms:
 >   (QPAT1 . QPAT2)       matches if QPAT1 matches the car and QPAT2 the cdr.
 >   [QPAT1 QPAT2..QPATn]  matches a vector of length n and QPAT1..QPATn match
 >                            its 0..(n-1)th elements, respectively.
 >   ,PAT                  matches if the ‘pcase’ pattern PAT matches.
 >   SYMBOL                matches if EXPVAL is ‘equal’ to SYMBOL.
 >   KEYWORD               likewise for KEYWORD.
 >   NUMBER                likewise for NUMBER.
 >   STRING                likewise for STRING.
 > 
 > The list or vector QPAT is a template.  The predicate formed
 > by a backquote-style pattern is a combination of those
 > formed by any sub-patterns, wrapped in a top-level condition:
 > EXPVAL must be "congruent" with the template.  For example:
 > 
 >   `(technical ,forum)
 > --8<---------------cut here---------------end--------------->8---
 > 
 > Or if you mean "_", then
 > 
 > --8<---------------cut here---------------start------------->8---
 >                   PATTERN can take one of the forms:
 > 
 >   _                matches anything.
 > --8<---------------cut here---------------end--------------->8---
 > 
 > which is familiar to people coming from functional languages, but even
 > Elisp uses underscores to denote unused variables.

-- 



^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: Instead of pcase
  2023-11-16 18:40       ` T.V Raman
@ 2023-11-16 19:13         ` Jim Porter
  0 siblings, 0 replies; 342+ messages in thread
From: Jim Porter @ 2023-11-16 19:13 UTC (permalink / raw)
  To: T.V Raman; +Cc: michael_heerdegen, emacs-devel

On 11/16/2023 10:40 AM, T.V Raman wrote:
> Yes. especially if a use I was trying to understand had some helpful
> guidance right next to it; that would also help one learn.

I'm hoping that putting examples in some separate place (e.g. shortdoc) 
would be helpful. By my count, there are 1182 calls to pcase in the 
Emacs tree, so it would be difficult to provide an intro to the syntax 
before every such use. (To be fair, 433 of those are in Org, but that 
still leaves us 749 cases in other parts of the tree.)

That said, for unusually-tricky uses of pcase, it would probably be nice 
to sprinkle in a few comments so you don't need to be a pcase master in 
order to understand what's going on.



^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: Instead of pcase
  2023-11-16 17:44     ` Michael Heerdegen
  2023-11-16 18:16       ` Philip Kaludercic
@ 2023-11-16 19:19       ` Eli Zaretskii
  2023-11-17  8:02         ` Michael Heerdegen
  1 sibling, 1 reply; 342+ messages in thread
From: Eli Zaretskii @ 2023-11-16 19:19 UTC (permalink / raw)
  To: Michael Heerdegen; +Cc: emacs-devel

> From: Michael Heerdegen <michael_heerdegen@web.de>
> Date: Thu, 16 Nov 2023 18:44:10 +0100
> 
> "T.V Raman" <raman@google.com> writes:
> 
> > I recently tried to understand some of the completion code; --
> > specifically, completion-at-point, and immediately hit the pcase wall
> > and gave up --- my lack of understanding of pcase made that code in
> > Emacs Core read like line-noise.
> 
> But that pcase form is only performing trivial destructuring.

If it does, then the node "Destructuring with pcase Patterns" Needs
Work™, because if you try to compare this fragment from
completion-at-point:

    (pcase res
      (`(,_ . ,(and (pred functionp) f)) (funcall f))
      (`(,hookfun . (,start ,end ,collection . ,plist))

with the example in the manual that explains destructuring, viz.:

       (pcase my-list
         (`(add ,x ,y)  (message "Contains %S and %S" x y)))

you will, I hope, see the difficulty of a newcomer to 'pcase' in
understanding how the code in completion-at-point is "only
destructuring".  IOW, if this code is "just destructuring", we don't
do a good-enough job of explaining that in the manual.



^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: Instead of pcase
  2023-11-16 18:11 ` Instead of pcase Emanuel Berg
@ 2023-11-16 19:26   ` Eli Zaretskii
  2023-11-16 22:16     ` Emanuel Berg
  0 siblings, 1 reply; 342+ messages in thread
From: Eli Zaretskii @ 2023-11-16 19:26 UTC (permalink / raw)
  To: Emanuel Berg; +Cc: emacs-devel

> From: Emanuel Berg <incal@dataswamp.org>
> Date: Thu, 16 Nov 2023 19:11:52 +0100
> 
> There are, according to the below code [last], 13 011 hits for
> cl-lib in the Emacs source. For pcase, there are 2168.
> So there is no kicking that out either.

Nonsense.  We already had such large replacements, and did that
without any trouble, though gradually.  Cases in point: setq-local,
defvar-keymap, and others.

So if we have an alternative that we like and is easy to use, we can
decide to replace pcase with it, and then do it, one case at a time.



^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: Instead of pcase
  2023-11-16 15:20 ` Spencer Baugh
@ 2023-11-16 20:16   ` Tomas Hlavaty
  2023-11-16 21:37     ` [External] : " Drew Adams
  2023-11-25  4:34     ` Stefan Monnier via Emacs development discussions.
  2023-11-18  3:03   ` combining cond and let, to replace pcase Richard Stallman
  1 sibling, 2 replies; 342+ messages in thread
From: Tomas Hlavaty @ 2023-11-16 20:16 UTC (permalink / raw)
  To: Spencer Baugh, emacs-devel

On Thu 16 Nov 2023 at 10:20, Spencer Baugh <sbaugh@janestreet.com> wrote:
> (let ((exp (if t '(foo . "str") '(bar . 7))))
>   (pcase exp
>     (`(foo . ,val) (concat "str" val))
>     (`(bar . ,val) (+ 1 val))))

(`(foo . ,val) (concat "str" val)) looks very strange.
One does not write (let ((,val ...)) ...).

Maybe (('foo . val) (concat "str" val)) would make more sense?

> and with cond-let one could write:
>
> (let ((exp (if t '(foo . "str") '(bar . 7))))
>   (cond-let
>    ((val
>      (and (eq (car exp) 'foo) (cdr exp)))
>     (concat "str" val))
>    ((val
>      (and (eq (car exp) 'bar) (cdr exp)))
>     (+ 1 val))))
>
> Which is maybe nicer?

(let ((exp (if t '(foo . "str") '(bar . 7))))
  (cl-case (car exp)
    (foo
     (when-let ((d (cdr exp)))
       (concat "str" val)))
    (bar
     (when-let ((d (cdr exp)))
       (1+ val)))))

It is a shame that case, ecase, typecase and etypecase are (were moved?)
to cl-lib.



^ permalink raw reply	[flat|nested] 342+ messages in thread

* RE: [External] : Re: Instead of pcase
  2023-11-16 20:16   ` Tomas Hlavaty
@ 2023-11-16 21:37     ` Drew Adams
  2023-11-25  4:34     ` Stefan Monnier via Emacs development discussions.
  1 sibling, 0 replies; 342+ messages in thread
From: Drew Adams @ 2023-11-16 21:37 UTC (permalink / raw)
  To: Tomas Hlavaty, Spencer Baugh, emacs-devel@gnu.org

> It is a shame that case, ecase, typecase and etypecase are (were moved?)
> to cl-lib.

+1.

(Not literally a shame - no shame.  But a pity.)




^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: Instead of pcase
  2023-11-16 19:26   ` Eli Zaretskii
@ 2023-11-16 22:16     ` Emanuel Berg
  2023-11-17  7:30       ` Eli Zaretskii
  0 siblings, 1 reply; 342+ messages in thread
From: Emanuel Berg @ 2023-11-16 22:16 UTC (permalink / raw)
  To: emacs-devel

Eli Zaretskii wrote:

>> There are, according to the below code [last], 13 011 hits
>> for cl-lib in the Emacs source. For pcase, there are 2168.
>> So there is no kicking that out either.
>
> Nonsense. We already had such large replacements, and did
> that without any trouble, though gradually. Cases in point:
> setq-local, defvar-keymap, and others.
>
> So if we have an alternative that we like and is easy to
> use, we can decide to replace pcase with it, and then do it,
> one case at a time.

We don't have alternatives that are better than cl-lib and
pcase, and their widespread use shows it.

This whole discussion is just disrespectful, polarizing and
alienating anti-cl-lib and now anti-pcase for no reason and
with no alternatives.

It is completely unrealistic to think anyone will write
replacements for cl-lib and pcase that are so superior, yet do
not contribute to complexity, that we can fully rely on
them instead.

But if that is what you are hoping for, why don't we revisit
this discussion if and when that happens?

-- 
underground experts united
https://dataswamp.org/~incal




^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: Instead of pcase
  2023-11-16 18:22 ` Jim Porter
@ 2023-11-16 22:55   ` Emanuel Berg
  2023-11-17  5:36   ` Po Lu
  1 sibling, 0 replies; 342+ messages in thread
From: Emanuel Berg @ 2023-11-16 22:55 UTC (permalink / raw)
  To: emacs-devel

Jim Porter wrote:

>> Those of you who are fans of `pcase' may not recognize the
>> cost it imposes on the Emacs Lisp language. You paid that
>> cost already, perhaps a few years ago, and perhaps you
>> enjoy each new language construct you learn. Perhaps, for
>> you, the more complexity of features to be learned,
>> the better.
>
> I'd like to offer a slightly different perspective here, as
> someone who only fairly recently became comfortable with
> Lisp (of any variety). I've used Emacs for a long time, but
> I found Lisp completely incomprehensible until just a couple
> of years ago. While getting started with Lisp isn't terribly
> complex, it's still quite a bit to learn, and it took
> a period where I was between jobs before I could dedicate
> the time I needed to get comfortable with writing Lisp.
>
> I encountered a lot of hurdles with Lisp along the way.
> The first one was extremely basic: I needed to get used to
> the style of indentation and develop an intuition for
> *reading* Lisp code, rather than slowly and laboriously
> translating it into a form I could understand more easily.
>
> The next hurdle was quoting. I still remember that one of my
> first patches to Emacs needed someone else to fix it in
> a followup because I messed up the quoting. The issues of
> quoting came up repeatedly for me as I encountered
> progressively more complex examples of quoting.
>
> This is where we get to 'pcase'. I'll agree that the upper
> limit on complex quoted forms in 'pcase' is very high.
> I've used 'pcase-defmacro' in one nontrivial case, and
> I found it very difficult to get right.
>
> *However*, 99% of the 'pcase' instances I've written or
> encountered are pretty simple for me to understand.
> Once I learned about 'pred' matcher and how to destructure
> via backquote patterns, it was mostly smooth sailing for me.
>
> Now, while I'd certainly say that I enjoy learning overall
> (or else I likely wouldn't have learned Lisp in the first
> place), I don't consider the complexity of a feature to be
> a positive. Instead, I prefer features that give me more
> power or better expressiveness. Often, that expressiveness
> comes at the cost of complexity under the hood (e.g.
> 'pcase-defmacro'), but that's not a positive to me in and
> of itself.
>
> Overall, 'pcase' is one of the parts of Elisp that
> I appreciate the most. Learning the basics of its
> mini-language took just a bit of reading. In addition to the
> docs, seeing examples helped: the first few times were a bit
> tricky to read, but I could usually understand what was
> happening, even if I couldn't (at the time) write my own
> 'pcase' code that worked. However, once I got the basics
> down, I quickly saw the benefits: I could combine a handful
> of basic tools to do bigger things, meaning I only need to
> know a small set of facts before I can tackle a complex
> task. This, to me, is the mark of a good language feature:
> I can compose it in ways that *multiply* the power of each
> (small, easy) bit.
>
> At a higher level, I'd say it's worth considering the
> audience we want to focus on. For veteran (Emacs) Lisp
> programmers, new additions like 'pcase' can increase the
> difficulty of reading new Elisp code: your prior mastery of
> the language isn't any good when you hit that "(pcase".
> However, many programmers today don't know Lisp, of any
> variety. For people like that, learning to contribute to
> Emacs means learning from the very beginning. Having gone
> through this, most of 'pcase' was very easy for me to pick
> up, and other parts of Elisp were much more challenging (it
> took me a long time to get comfortable with writing macros,
> which is also probably one of the reasons I found
> 'pcase-defmacro' to be so tricky).
>
> That said, it's true that every feature we add to Elisp
> increases the overall complexity because now there are more
> things to learn. However, in my opinion, the expressiveness
> of 'pcase' far outweighs this cost.

Well said! Thank you for this post. I agree, and I enjoyed
reading it.

-- 
underground experts united
https://dataswamp.org/~incal




^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: Instead of pcase
  2023-11-16 17:18   ` T.V Raman
  2023-11-16 17:44     ` Michael Heerdegen
  2023-11-16 18:21     ` Dmitry Gutov
@ 2023-11-16 23:41     ` Emanuel Berg
  2023-11-17  7:34       ` Eli Zaretskii
  2 siblings, 1 reply; 342+ messages in thread
From: Emanuel Berg @ 2023-11-16 23:41 UTC (permalink / raw)
  To: emacs-devel

T.V Raman wrote:

> RMS' message makes some very valuable points re specialized
> languages like pcase -- pcase has its strengths, but in
> general, it's definitely not easy to understand complex code
> that leverages it -- as an example:
>
> I recently tried to understand some of the completion code;
> -- specifically, completion-at-point, and immediately hit
> the pcase wall and gave up --- my lack of understanding of
> pcase made that code in Emacs Core read like line-noise.

I grepped my own Elisp for pcase and found this.
Interestingly, it uses cl-lib as well. So here we have cl-lib
and pcase in combination, so should be downright
incomprehensible, right?

You will see that the use of pcase is very clear. I'm sure you
can understand it. From there, more complex use should be very
possible for you to understand as well, I'm positive.

But really: code that is difficult to understand can be
written using non-cl-lib Elisp and non-pcase Elisp as well.
Good use of cl-lib and good use of pcase reduces complexity.
Complex use of cl-lib and pcase will be complex, sure, but
there are no guarantees solving that complexity in any other
way will be any less complex.

If everyone did that instead of using libraries we would end
up with much more code, and code that essentially - but not
quite, and that would be a big problem - did the same thing
over and over.

;;; -*- lexical-binding: t -*-
;;
;; this file:
;;   https://dataswamp.org/~incal/emacs-init/time-cmp.el

(require 'cl-lib)
(require 'pcase)

(defun days (y1 m1 d1 y2 m2 d2)
  (let*((then (float-time (encode-time 0 0 0 d1 m1 y1)))
        (now  (float-time (encode-time 0 0 0 d2 m2 y2)))
        (diff (- now then)) )
    (string-to-number (format-seconds "%d" diff)) ))

;; (days 1958 04 13 1958 08 30) ; 139 days between Tahiti Nui 2 & 3

(defun days-date (date1 date2)
  (pcase-let*(
      (sep "-")
      (`(,y1 ,m1 ,d1) (cl-map 'list #'string-to-number (split-string date1 sep)))
      (`(,y2 ,m2 ,d2) (cl-map 'list #'string-to-number (split-string date2 sep))) )
    (days y1 m1 d1 y2 m2 d2) ))

;; (days-date "2021-03-19" "2021-04-20") ;     31
;; (days-date "1964-07-26" "2021-03-22") ; 20 693

-- 
underground experts united
https://dataswamp.org/~incal




^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: Instead of pcase
  2023-11-16 18:22 ` Jim Porter
  2023-11-16 22:55   ` Emanuel Berg
@ 2023-11-17  5:36   ` Po Lu
  2023-11-19 11:48     ` Michael Heerdegen
  1 sibling, 1 reply; 342+ messages in thread
From: Po Lu @ 2023-11-17  5:36 UTC (permalink / raw)
  To: Jim Porter; +Cc: rms, emacs-devel

Jim Porter <jporterbugs@gmail.com> writes:

> At a higher level, I'd say it's worth considering the audience we want
> to focus on. For veteran (Emacs) Lisp programmers, new additions like
> 'pcase' can increase the difficulty of reading new Elisp code: your
> prior mastery of the language isn't any good when you hit that
> "(pcase". However, many programmers today don't know Lisp, of any
> variety. For people like that, learning to contribute to Emacs means
> learning from the very beginning.

That's as may be, but pcase remains a hurdle all Emacs Lisp programmers
will have to surmount, if they are to understand a program which employs
it.  Much as the linguistically inclined enjoy acquiring an abstruse
language, so certain programmers may relish the occasion to acquire a
new and intricate construct.  Nevertheless, and your singular experience
notwithstanding, other programmers are loath to devote their time to
such monotonous pursuits--whether they are learning the language from a
blank slate or with a solid basis in the form of proficiency in other
dialects of Lisp--and they are a sizable portion of our userbase as
well.  All these programmers share a common ground that excludes pcase
and presently destructuring variable binding, so I don't think there are
many who would gainsay that the introduction of a simpler construct to
the same end is a win-win.

Now for some quibbling: there is no "audience" for whom our design
choices are made; rather a corpus of users who are enjoined to read and
write the same language.  It is to everyone's advantage if the users
with such zeal as to memorize and enjoy these ivory tower delights exert
themselves slightly, in order for others to read their code also.



^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: Instead of pcase
  2023-11-16 22:16     ` Emanuel Berg
@ 2023-11-17  7:30       ` Eli Zaretskii
  2023-11-17  8:09         ` Emanuel Berg
  0 siblings, 1 reply; 342+ messages in thread
From: Eli Zaretskii @ 2023-11-17  7:30 UTC (permalink / raw)
  To: Emanuel Berg; +Cc: emacs-devel

> From: Emanuel Berg <incal@dataswamp.org>
> Date: Thu, 16 Nov 2023 23:16:26 +0100
> 
> Eli Zaretskii wrote:
> 
> >> There are, according to the below code [last], 13 011 hits
> >> for cl-lib in the Emacs source. For pcase, there are 2168.
> >> So there is no kicking that out either.
> >
> > Nonsense. We already had such large replacements, and did
> > that without any trouble, though gradually. Cases in point:
> > setq-local, defvar-keymap, and others.
> >
> > So if we have an alternative that we like and is easy to
> > use, we can decide to replace pcase with it, and then do it,
> > one case at a time.
> 
> We don't have alternatives that are better than cl-lib and
> pcase, and their widespread use shows it.

First, I was talking about pcase, not the rest.

Second, I said "IF we have an alternatives that we like".  It goes
without saying that we don't have such an alternative for pcase at
this time, and maybe never will.

My point was a simple one: IF we have an alternative that we like,
THEN we can decide to make these replacements, and will have no
problems whatsoever doing so, as we have done in other cases.  IOW, I
was only objecting to your claim that such a replacement is impossible
due to the sheer quantity of pcase uses in the tree, not to any other
arguments in this thread.

> This whole discussion is just disrespectful, polarizing and
> alienating anti-cl-lib and now anti-pcase for no reason and
> with no alternatives.

Nonsense.  There's no disrespect in discussing the various advanced
ELisp facilities and their impact on our coding conventions.

> It is completely unrealistic to think anyone will write
> replacements for cl-lib and pcase

If so, you have nothing to worry about: the above is just an academic
discussion that will never have any practical effect.  So please relax
and cool down.

> But if that is what you are hoping for, why don't we revisit
> this discussion if and when that happens?

The only thing I'm hoping for is for Emacs to get better and continue
its development.  If that is wrong, maybe you want to step up and
replace me as Emacs maintainer?



^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: Instead of pcase
  2023-11-16 23:41     ` Emanuel Berg
@ 2023-11-17  7:34       ` Eli Zaretskii
  0 siblings, 0 replies; 342+ messages in thread
From: Eli Zaretskii @ 2023-11-17  7:34 UTC (permalink / raw)
  To: Emanuel Berg; +Cc: emacs-devel

> From: Emanuel Berg <incal@dataswamp.org>
> Date: Fri, 17 Nov 2023 00:41:43 +0100
> 
> I grepped my own Elisp for pcase and found this.
> Interestingly, it uses cl-lib as well.

No, pcase.el doesn't use cl-lib.



^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: Instead of pcase
  2023-11-16 19:19       ` Instead of pcase Eli Zaretskii
@ 2023-11-17  8:02         ` Michael Heerdegen
  0 siblings, 0 replies; 342+ messages in thread
From: Michael Heerdegen @ 2023-11-17  8:02 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: emacs-devel

Eli Zaretskii <eliz@gnu.org> writes:

> If it does,

It doesn't.  Was very tired yesterday without being aware of it.  Sorry
again for the confusion I caused.

> then the node "Destructuring with pcase Patterns" Needs
> Work™, because if you try to compare this fragment from
> completion-at-point:
>
>     (pcase res
>       (`(,_ . ,(and (pred functionp) f)) (funcall f))
>       (`(,hookfun . (,start ,end ,collection . ,plist))

The subpattern

  (and (pred functionp) f)

contains of course more syntactical elements: `and', a `pred' test, and
a variable used for binding.  Which means: This matches anything
fulfilling `functionp' and binds the variable `f' to the element at that
position.


Michael.



^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: Instead of pcase
  2023-11-17  7:30       ` Eli Zaretskii
@ 2023-11-17  8:09         ` Emanuel Berg
  2023-11-17 12:16           ` Eli Zaretskii
  0 siblings, 1 reply; 342+ messages in thread
From: Emanuel Berg @ 2023-11-17  8:09 UTC (permalink / raw)
  To: emacs-devel

Eli Zaretskii wrote:

>> But if that is what you are hoping for, why don't we
>> revisit this discussion if and when that happens?
>
> The only thing I'm hoping for is for Emacs to get better and
> continue its development. If that is wrong, maybe you want
> to step up and replace me as Emacs maintainer?

Pro hint: Don't start this kind of campaigns against libraries
your own software is relying on, only for vague reasons of
style and complexity, and with no alternative in sight. No one
is going to react positively to that and it won't help Emacs
development, as it only creates bad blood in the community for
no reason.

-- 
underground experts united
https://dataswamp.org/~incal




^ permalink raw reply	[flat|nested] 342+ messages in thread

* Complex SPEC for variables/customization like font-lock-keywords/org-capture-templates/etc (was: Instead of pcase)
  2023-11-16 18:16       ` Philip Kaludercic
@ 2023-11-17  8:54         ` Ihor Radchenko
  2023-11-25  4:03           ` Complex SPEC for variables/customization like font-lock-keywords/org-capture-templates/etc Stefan Monnier
  0 siblings, 1 reply; 342+ messages in thread
From: Ihor Radchenko @ 2023-11-17  8:54 UTC (permalink / raw)
  To: Philip Kaludercic; +Cc: Michael Heerdegen, emacs-devel

Philip Kaludercic <philipk@posteo.net> writes:

> Michael Heerdegen <michael_heerdegen@web.de> writes:
>
> ...  If one has to talk about difficult to understand/remember
> domain specific languages, then `font-lock-defaults' would be a much
> more pressing candidate.

Or font-lock-keywords... Last time I were seriously developing new
keywords, I had to do it by trial-and-error and even examine font-lock
sources.

We also have similar issues with complex specifications in Org mode -
org-capture-templates, org-agenda-custom-commands, etc.

I believe that it is a general problem relevant various non-trivial
variables/customization we have across Emacs and Emacs packages -
developers, or, more frequently, Emacs users have significant
difficulties understanding the obscure ad-hoc languages we have to
invent for font-locking, templates, etc.

The most common confusions are related to:

1. Quoting deeply nested lists
2. Keeping track of what each of the list elements refers to.
   For example, font-lock-keywords may contain something like
   
   (lisp--match-hidden-arg
   (0
    '(face font-lock-warning-face help-echo
	   "Easy to misread; consider moving the element to the next line")
    prepend))

    It is hard to parse without constantly examining the docstring.

Customize interface somewhat helps with (2), but many users avoid it and
instead prefer to write init.el manually. Also, developers cannot even
use customize interface (for example when developing
font-lock-keywords).

(1) is also a rather common problem, especially when both quoted and
unquoted version of a list element are technically valid (for example,
consider 'face-name vs. face-name in font-lock-keywords - a rather
common confusion for me).

I do not know a good solution to the above, and thus would like to
discuss this problem.

Some possible ideas:

1. Provide some universal mechanism for type-validation of variables.
   Something similar to :type spec in defcustom, but for Elisp
   variables. This will at least catch invalid values.

2. Provide custom warning mechanism catching common mistakes in the
   variables SPEC. For example, 'face-name vs. face-name for
   font-lock-keywords in the above example.

3. Enhance eldoc to show a tip about variable value structure, similar
   to what is done for function arguments.

-- 
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] 342+ messages in thread

* Re: Instead of pcase
  2023-11-17  8:09         ` Emanuel Berg
@ 2023-11-17 12:16           ` Eli Zaretskii
  2023-11-18  6:26             ` Emanuel Berg
  0 siblings, 1 reply; 342+ messages in thread
From: Eli Zaretskii @ 2023-11-17 12:16 UTC (permalink / raw)
  To: Emanuel Berg; +Cc: emacs-devel

> From: Emanuel Berg <incal@dataswamp.org>
> Date: Fri, 17 Nov 2023 09:09:46 +0100
> 
> Eli Zaretskii wrote:
> 
> >> But if that is what you are hoping for, why don't we
> >> revisit this discussion if and when that happens?
> >
> > The only thing I'm hoping for is for Emacs to get better and
> > continue its development. If that is wrong, maybe you want
> > to step up and replace me as Emacs maintainer?
> 
> Pro hint: Don't start this kind of campaigns against libraries
> your own software is relying on, only for vague reasons of
> style and complexity, and with no alternative in sight.

Reality check: I didn't start this thread.  My personal contributions
to it are quite modest: mainly correcting inaccuracies and mistakes in
messages posted to others, so as to avoid tricking people into
incorrect conclusions due to these inaccuracies.

> No one is going to react positively to that and it won't help Emacs
> development, as it only creates bad blood in the community for no
> reason.

If you are actually reading the messages in this thread, you will
realize that your assertions are false.  Some people here actually
agree that pcase presents a difficulty (others disagree), and I
spotted no bad blood here from people who voiced their opinions.  So I
think you see problems where there are none.



^ permalink raw reply	[flat|nested] 342+ messages in thread

* combining cond and let, to replace pcase.
  2023-11-16 15:20 ` Spencer Baugh
  2023-11-16 20:16   ` Tomas Hlavaty
@ 2023-11-18  3:03   ` Richard Stallman
  2023-11-19 11:20     ` Michael Heerdegen
                       ` (3 more replies)
  1 sibling, 4 replies; 342+ messages in thread
From: Richard Stallman @ 2023-11-18  3:03 UTC (permalink / raw)
  To: Spencer Baugh; +Cc: emacs-devel

[[[ To any NSA and FBI agents reading my email: please consider    ]]]
[[[ whether defending the US Constitution against all enemies,     ]]]
[[[ foreign or domestic, requires you to follow Snowden's example. ]]]

  > I've thought before that it would be nice to have a cond-let construct,
  > like if-let and when-let.

Here's an example to show what I have come up with along these lines:

(cond* (:bind (x foobar) y z (foo 5) a)  ;; variables to bind, as in let
       ;; I'm also thinking of using nil instead of :bind.

       ;; t as condition means run this clause unconditionally
       ;; then continue with next clause.
       (t do-this-unconditionally-and-dont-stop...)

       ;; Tests with a new function `match' which I'm going to work on next.
       ((match x 'foo) ...)

       ;; t in the last clause means the same as in previous clauses,
       ;; but you can think of it as being the same as in `cond'.
       (t do-this-as-last-resort)
       )

Rhe idea is that conf* does part of pcase's added functionality, and
`match' will do the rest.  But it is not necessary to cram _all_ the
additional matching functionality (to compare to pcase) into a single
new function.  We could have more than one new function, eacn for its
own kind of pattern matching.

Some of them could do destructuring as well as matching.

I hoipe that using a few constructs to divide up the job will avoid
the kludginess of pcase's bells-and-whistles-for-everything approach,
resulting in something equally convenient but made of simple components.

-- 
Dr Richard Stallman (https://stallman.org)
Chief GNUisance of the GNU Project (https://gnu.org)
Founder, Free Software Foundation (https://fsf.org)
Internet Hall-of-Famer (https://internethalloffame.org)





^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: Instead of pcase
  2023-11-16 18:47         ` Philip Kaludercic
  2023-11-16 18:51           ` T.V Raman
@ 2023-11-18  3:04           ` Richard Stallman
  2023-11-19 12:23             ` Michael Heerdegen
  2023-11-19 13:49             ` Dmitry Gutov
  1 sibling, 2 replies; 342+ messages in thread
From: Richard Stallman @ 2023-11-18  3:04 UTC (permalink / raw)
  To: Philip Kaludercic; +Cc: emacs-devel

[[[ To any NSA and FBI agents reading my email: please consider    ]]]
[[[ whether defending the US Constitution against all enemies,     ]]]
[[[ foreign or domestic, requires you to follow Snowden's example. ]]]

        > (`(,_ . ,(and (pred functionp) f)) (funcall f))
        > (`(,hookfun . (,start ,end ,collection . ,plist))

I read the Info documentation of pcase a few days ago and I can't
recall the rules for understanding those two pcase clauses.  What I
recall is that they are not to be interpreted as Lisp expressions.
They contain code that looks like Lisp but does not have the same
semantic rules as Lisp.

    `(,_ . ,(and (pred functionp) f))

is not Lisp.

    `(,hookfun . (,start ,end ,collection . ,plist)

is not Lisp either.  That list would be meaningful as a Lisp
expression but what it means here is different.

That is a consequence of the terse little language that pcase defines.

-- 
Dr Richard Stallman (https://stallman.org)
Chief GNUisance of the GNU Project (https://gnu.org)
Founder, Free Software Foundation (https://fsf.org)
Internet Hall-of-Famer (https://internethalloffame.org)





^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: Instead of pcase
  2023-11-17 12:16           ` Eli Zaretskii
@ 2023-11-18  6:26             ` Emanuel Berg
  2023-11-18  7:21               ` Po Lu
  0 siblings, 1 reply; 342+ messages in thread
From: Emanuel Berg @ 2023-11-18  6:26 UTC (permalink / raw)
  To: emacs-devel

Eli Zaretskii wrote:

> If you are actually reading the messages in this thread, you
> will realize that your assertions are false. Some people
> here actually agree that pcase presents a difficulty (others
> disagree), and I spotted no bad blood here from people who
> voiced their opinions. So I think you see problems where
> there are none.

Bottom line, not using advanced libraries and instead rely on
some basic building block Elisp is a total bogus idea, sorry.

-- 
underground experts united
https://dataswamp.org/~incal




^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: Instead of pcase
  2023-11-18  6:26             ` Emanuel Berg
@ 2023-11-18  7:21               ` Po Lu
  2023-11-18  7:41                 ` Eli Zaretskii
  0 siblings, 1 reply; 342+ messages in thread
From: Po Lu @ 2023-11-18  7:21 UTC (permalink / raw)
  To: emacs-devel

Emanuel Berg <incal@dataswamp.org> writes:

> Bottom line, not using advanced libraries and instead rely on
> some basic building block Elisp is a total bogus idea, sorry.

That's merely your inference, so long as "advanced libraries" refers to
pcase.  I don't expect anything short of obstinately maintaining that
it's true from you, but bear in mind that many others disagree, and,
above all, the subject at hand is the design of a construct that enables
pcase to be replaced without forsaking conciseness.  A new construct.
Not constraining ourselves to "some basic building block Elisp."

With these conversations the game is frequently not worth the candle,
because of bitter but inane comments like yours.



^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: Instead of pcase
  2023-11-18  7:21               ` Po Lu
@ 2023-11-18  7:41                 ` Eli Zaretskii
  0 siblings, 0 replies; 342+ messages in thread
From: Eli Zaretskii @ 2023-11-18  7:41 UTC (permalink / raw)
  To: Po Lu; +Cc: emacs-devel

> From: Po Lu <luangruo@yahoo.com>
> Date: Sat, 18 Nov 2023 15:21:09 +0800
> 
> Emanuel Berg <incal@dataswamp.org> writes:
> 
> > Bottom line, not using advanced libraries and instead rely on
> > some basic building block Elisp is a total bogus idea, sorry.
> 
> That's merely your inference, so long as "advanced libraries" refers to
> pcase.  I don't expect anything short of obstinately maintaining that
> it's true from you, but bear in mind that many others disagree, and,
> above all, the subject at hand is the design of a construct that enables
> pcase to be replaced without forsaking conciseness.  A new construct.
> Not constraining ourselves to "some basic building block Elisp."
> 
> With these conversations the game is frequently not worth the candle,
> because of bitter but inane comments like yours.

Po Lu, if you don't have anything constructive or useful to say about
someone else's comments, except that you don't like them, please
consider saying nothing at all.  There's no need to rebuke each and
every opinion contrary to yours, just to say once again that you
disagree.  Your opinions in this matter were voiced and noted, so no
need to reiterate them, let alone in a rude way that includes personal
attacks.

Let's please try to lower the noise level here, not raise it.



^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: combining cond and let, to replace pcase.
  2023-11-18  3:03   ` combining cond and let, to replace pcase Richard Stallman
@ 2023-11-19 11:20     ` Michael Heerdegen
  2023-11-19 11:43       ` Eli Zaretskii
                         ` (3 more replies)
  2023-11-19 16:08     ` Axel Forsman
                       ` (2 subsequent siblings)
  3 siblings, 4 replies; 342+ messages in thread
From: Michael Heerdegen @ 2023-11-19 11:20 UTC (permalink / raw)
  To: Richard Stallman; +Cc: Spencer Baugh, emacs-devel

Richard Stallman <rms@gnu.org> writes:

> Some of them could do destructuring as well as matching.
>
> I hoipe that using a few constructs to divide up the job will avoid
> the kludginess of pcase's bells-and-whistles-for-everything approach,
> resulting in something equally convenient but made of simple
> components.

I really don't know how you come to such a conclusion.

The original docstring of `pcase' was half of a screen page and it was
_complete_.  Syntax and semantics are simple, nearly trivial, and
consistent.  It took one minute for me to learn everything.  Then the
doc has been extended to the current form adding more prose, in my eyes,
it added not a single bit of information.

If some people have a problem understanding the abstract approach, this
is something different.  But a "kludginess of pcase's
bells-and-whistles-for-everything approach" does not exist.  So please
understand that your approach will make the situation worse for others.

To me this discussion looks like some people aren't willing to accept
multiplication like 10*5 because it "looks strange" and "one would rather
write "5+5+5+5+5+5+5+5+5+5" because this would be much simpler and we
don't need this strange "*" at all.

Is this unfair?  I don't know.  But are there any _objective_ reasons
why the design of `pcase' would not be optimal?  To me this all looks
more like being based on vague feelings because the approach is a bit
different from what people are used to.  But the approach is extremely
simple.  I think that replacing it with multiple other tools would
complicate the matter.


Any additionally defined pcase macros are a different thing of
course. They extend pcase patterns to a richer but more complicated
mini-language.  You need to remember more definitions.  OTOH, this is
not a design fault of pcase patterns: any matching tool that wants to
provide specialized tools to support matching of special things (like
structs) will have to extend the semantics in one way or the other, and
necessarily complicate the tool(s).


To sum up, I question your premise of this discussion.  In my opinion
`pcase' comes very close to the optimal solution for its task.  For
some reason, people don't accept the backquote syntax it uses, although
it perfectly fits the task of destructuring.  I just don't understand it.
People get crazy about that backquote.  Dunno what's the matter with it.
But it seems this is one of the main problems.


Michael.



^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: combining cond and let, to replace pcase.
  2023-11-19 11:20     ` Michael Heerdegen
@ 2023-11-19 11:43       ` Eli Zaretskii
  2023-11-19 12:16         ` Gerd Möllmann
  2023-11-19 12:50         ` Michael Heerdegen
  2023-11-19 12:04       ` Gerd Möllmann
                         ` (2 subsequent siblings)
  3 siblings, 2 replies; 342+ messages in thread
From: Eli Zaretskii @ 2023-11-19 11:43 UTC (permalink / raw)
  To: Michael Heerdegen; +Cc: rms, sbaugh, emacs-devel

> From: Michael Heerdegen <michael_heerdegen@web.de>
> Cc: Spencer Baugh <sbaugh@janestreet.com>,  emacs-devel@gnu.org
> Date: Sun, 19 Nov 2023 12:20:20 +0100
> 
> To sum up, I question your premise of this discussion.

Don't.  It's a real issue.  Maybe not for you, but for some others.
No one in their right mind would assume that Richard has "a problem
understanding the abstract approach".  Just look at which pieces of
software he wrote and the various DSLs he designed while at that.  So
when Richard, of all the people, tells us there's a problem, I suggest
that we listen, especially since a few other veteran Emacs developers,
who are not unfamiliar with Emacs Lisp and its subtleties, tell
something similar if not identical.

It could be that pcase is not a problem for you, but that's not what
this discussion is about.  When on several occasions I told you that
some piece of documentation is clear for me, you still insisted for it
to be fixed because it wasn't clear for you, and you were right.
Because the documentation I write is not for me, it's for others.

> In my opinion `pcase' comes very close to the optimal solution for
> its task.

The same is true for regular expressions.  But we still have rx, and
some people really prefer it.  Maybe this imperfect analogy will help
you understand the issue with pcase.



^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: Instead of pcase
  2023-11-17  5:36   ` Po Lu
@ 2023-11-19 11:48     ` Michael Heerdegen
  2023-11-19 12:50       ` Eli Zaretskii
  2023-11-19 14:29       ` Po Lu
  0 siblings, 2 replies; 342+ messages in thread
From: Michael Heerdegen @ 2023-11-19 11:48 UTC (permalink / raw)
  To: Po Lu; +Cc: Jim Porter, rms, emacs-devel

Po Lu <luangruo@yahoo.com> writes:

> Much as the linguistically inclined enjoy acquiring an abstruse
> language, so certain programmers may relish the occasion to acquire a
> new and intricate construct.  Nevertheless, and your singular
> experience notwithstanding

"abstruse language" - "singular experience" ...(?) - sorry, are we people
having understood pcase in few minutes some kind of aliens, compared to
the "normal people"?  Do we not count?  Because we are not loud
and angry and outraged?

For you it seems to be a fact that `pcase' is something complicated and
most people don't like it.  Eh - no?  Pardon - but when I was able to
learn `pcase' in one minute from a few lines of the original docstring,
there must be something missing in that picture.  I don't know why it is
harder for you to learn it.  But something is not a fact because you
feel like it would be.

What I don't like here in this discussion is that some people are not
willing to accept that other people make different experiences with the
same things.  This is the death to any constructive discussion.  It is
impossible to find a good solution for everybody under such
circumstances.

And note that you are weakening your position when discussing like this.
I can't take someone seriously when I see that s?he is not able to think
along the viewpoints of others.

Interesting would be to hear concrete arguments, but we heard nearly
none.  "I'm angry" is not an argument.


Michael.



^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: combining cond and let, to replace pcase.
  2023-11-19 11:20     ` Michael Heerdegen
  2023-11-19 11:43       ` Eli Zaretskii
@ 2023-11-19 12:04       ` Gerd Möllmann
  2023-11-19 18:10       ` Tomas Hlavaty
  2023-11-19 21:36       ` Alan Mackenzie
  3 siblings, 0 replies; 342+ messages in thread
From: Gerd Möllmann @ 2023-11-19 12:04 UTC (permalink / raw)
  To: Michael Heerdegen; +Cc: Richard Stallman, Spencer Baugh, emacs-devel

Michael Heerdegen <michael_heerdegen@web.de> writes:

> Is this unfair?  I don't know.  But are there any _objective_ reasons
> why the design of `pcase' would not be optimal?  To me this all looks
> more like being based on vague feelings because the approach is a bit
> different from what people are used to.

Kind of the same here.

And I'm quasi waiting for the next thing to pop up, say generic
functions, or generelized variables (gv.el). I'm wondering where the
journey goes.



^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: combining cond and let, to replace pcase.
  2023-11-19 11:43       ` Eli Zaretskii
@ 2023-11-19 12:16         ` Gerd Möllmann
  2023-11-19 13:21           ` Eli Zaretskii
  2023-11-19 16:03           ` Joost Kremers
  2023-11-19 12:50         ` Michael Heerdegen
  1 sibling, 2 replies; 342+ messages in thread
From: Gerd Möllmann @ 2023-11-19 12:16 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: Michael Heerdegen, rms, sbaugh, emacs-devel

Eli Zaretskii <eliz@gnu.org> writes:

>> From: Michael Heerdegen <michael_heerdegen@web.de>
>> Cc: Spencer Baugh <sbaugh@janestreet.com>,  emacs-devel@gnu.org
>> Date: Sun, 19 Nov 2023 12:20:20 +0100
>> 
>> To sum up, I question your premise of this discussion.
>
> Don't.  It's a real issue.  Maybe not for you, but for some others.
> No one in their right mind would assume that Richard has "a problem
> understanding the abstract approach".  Just look at which pieces of
> software he wrote and the various DSLs he designed while at that.  So
> when Richard, of all the people, tells us there's a problem, I suggest
> that we listen, especially since a few other veteran Emacs developers,
> who are not unfamiliar with Emacs Lisp and its subtleties, tell
> something similar if not identical.

One should always listen, almost always anyway, IMO. You named a few
reasons.

But to the full truth also belongs that Richard has stopped programming
completely in 2008, says he himself, and that he doesn't seem to be very
familiar with current Elisp, if he's seen pcase for the first time a few
days ago. One must keep that in mind.



^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: Instead of pcase
  2023-11-18  3:04           ` Richard Stallman
@ 2023-11-19 12:23             ` Michael Heerdegen
  2023-11-19 16:02               ` Barry Fishman
  2023-11-19 13:49             ` Dmitry Gutov
  1 sibling, 1 reply; 342+ messages in thread
From: Michael Heerdegen @ 2023-11-19 12:23 UTC (permalink / raw)
  To: Richard Stallman; +Cc: Philip Kaludercic, emacs-devel

Richard Stallman <rms@gnu.org> writes:

> I read the Info documentation of pcase a few days ago and I can't
> recall the rules for understanding those two pcase clauses.  What I
> recall is that they are not to be interpreted as Lisp expressions.

> They contain code that looks like Lisp but does not have the same
> semantic rules as Lisp.
>
>     `(,_ . ,(and (pred functionp) f))
>
> is not Lisp.
>
>     `(,hookfun . (,start ,end ,collection . ,plist)
>
> is not Lisp either.

I more and more come to the conclusion that the backquote syntax is more
or less the central point that scares or confuses (some) people.

So you would rather prefer to have a normal function that returns a
matcher (if you want just "Lisp")?

What functions could be used to describe a pattern matching lists of a
certain structure?  I guess it would be the easiest approach if we could
still use the names we already know: list, car, cdr.  Hmm - actually the
most compact mean to construct more complicated lists is backquote.  And
that's what you have above.  The only thing you need to remember is that
elements you "insert" or "splice in" are again pattern descriptions
matching the elements at that position.  How could it be even simpler?
Once you accepted that backquote is used for a different, but parallel
semantics here, everything suddenly gets absolutely trivial.

But I see your point, it's not Lisp.  I guess it should be possible to
change that.  We could define a set of functions to construct a matcher.

This would make the pattern specifications less compact and for some of
us harder to read (more verbosity), but it should be possible.  We could
even have some kind of converter between the two representations of
pattern specifications.  This leads me to a realization:

A "normal Lisp" approach would still need to define replacements for all
of the constructs.  (pred FUN . ARGS) would have to be replaced by
something like (make-matching-fun FUN &optional ARGS).  You would
still have to remember the exactly same details: what are the semantics
of the returned pattern; when there are ARGS specified, at which
argument position is the matched thing specified when FUN will be
called?  How to correctly negate this pattern?  Will the matching
algorithm backtrack when the pattern is negated?

So, the advantage would be more of a psychological kind: you have normal
Lisp function calls, but structurally you have the same thing, and you
have to remember exactly the same set of details.  The complexity comes
from the task, not from the implementation.


Michael.



^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: Instead of pcase
  2023-11-19 11:48     ` Michael Heerdegen
@ 2023-11-19 12:50       ` Eli Zaretskii
  2023-11-19 14:05         ` Dmitry Gutov
  2023-11-19 14:14         ` Michael Heerdegen
  2023-11-19 14:29       ` Po Lu
  1 sibling, 2 replies; 342+ messages in thread
From: Eli Zaretskii @ 2023-11-19 12:50 UTC (permalink / raw)
  To: Michael Heerdegen; +Cc: luangruo, jporterbugs, rms, emacs-devel

> From: Michael Heerdegen <michael_heerdegen@web.de>
> Cc: Jim Porter <jporterbugs@gmail.com>,  rms@gnu.org,  emacs-devel@gnu.org
> Date: Sun, 19 Nov 2023 12:48:08 +0100
> 
> What I don't like here in this discussion is that some people are not
> willing to accept that other people make different experiences with the
> same things.

This goes both ways, you know.



^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: combining cond and let, to replace pcase.
  2023-11-19 11:43       ` Eli Zaretskii
  2023-11-19 12:16         ` Gerd Möllmann
@ 2023-11-19 12:50         ` Michael Heerdegen
  2023-11-19 13:08           ` Eli Zaretskii
  1 sibling, 1 reply; 342+ messages in thread
From: Michael Heerdegen @ 2023-11-19 12:50 UTC (permalink / raw)
  To: emacs-devel

Eli Zaretskii <eliz@gnu.org> writes:

> > To sum up, I question your premise of this discussion.
>
> Don't.  It's a real issue.  Maybe not for you, but for some others.
> No one in their right mind would assume that Richard has "a problem
> understanding the abstract approach".  Just look at which pieces of
> software he wrote and the various DSLs he designed while at that.  So
> when Richard, of all the people, tells us there's a problem, I suggest
> that we listen, especially since a few other veteran Emacs developers,
> who are not unfamiliar with Emacs Lisp and its subtleties, tell
> something similar if not identical.

There is a problem.  And I see it.  I already said that.

But the problem is "some people can't read pcase calls well".  The
problem is not "pcase is bad".  The latter is a subjective conclusion,
and this is the part I do not accept as objective truth.

And this makes a difference to how we aim to find a solution.  Maybe we
people actually understanding pcase could also contribute something to a
solution?  This is not possible if "pcase is badly designed" is the
starting point of the discussion that everybody should take as granted
objective truth that is meant to be blindly accepted - I don't do that.

I accept that people having a problem reading code involving pcase is a
problem.

> The same is true for regular expressions.  But we still have rx, and
> some people really prefer it.  Maybe this imperfect analogy will help
> you understand the issue with pcase.

This is an excellent analogy.  Which one is the counterpart to `pcase'?
`rx' or the string form?

Actually both and none, this is exactly the point I raised in my other
reply - both have exactly the same complexity, and it is totally
subjective and only habit which one you prefer.  The amount of knowledge
you need to remember, the amount of documentation you need to consult,
is the same.  And although the string form is normal Lisp (strings are
expressions), this fact makes the thing not any easier to use, not a
tiny bit.  The complexity is in the task.  And hidden in the algorithm
that runs after you have specified the pattern/the regexp in whatever
language you prefer.


Michael.




^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: combining cond and let, to replace pcase.
  2023-11-19 12:50         ` Michael Heerdegen
@ 2023-11-19 13:08           ` Eli Zaretskii
  2023-11-19 13:52             ` Michael Heerdegen
  2023-11-19 13:59             ` Dmitry Gutov
  0 siblings, 2 replies; 342+ messages in thread
From: Eli Zaretskii @ 2023-11-19 13:08 UTC (permalink / raw)
  To: Michael Heerdegen; +Cc: emacs-devel

> From: Michael Heerdegen <michael_heerdegen@web.de>
> Date: Sun, 19 Nov 2023 13:50:26 +0100
> 
> There is a problem.  And I see it.  I already said that.
> 
> But the problem is "some people can't read pcase calls well".  The
> problem is not "pcase is bad".  The latter is a subjective conclusion,
> and this is the part I do not accept as objective truth.

Code that is hard to read, even if only to some of the people, is a
problem for us, since we are a project that advances mainly through
sporadic contributions of people who tend to disappear after a
relatively short time.

> I accept that people having a problem reading code involving pcase is a
> problem.

So we agree.  Then arguments about how easy pcase is for some are not
relevant, because this is not what this is about, right?

> > The same is true for regular expressions.  But we still have rx, and
> > some people really prefer it.  Maybe this imperfect analogy will help
> > you understand the issue with pcase.
> 
> This is an excellent analogy.  Which one is the counterpart to `pcase'?
> `rx' or the string form?

The string, of course.

> Actually both and none, this is exactly the point I raised in my other
> reply - both have exactly the same complexity, and it is totally
> subjective and only habit which one you prefer.

It isn't only that.  It is also that the obscure and subtle nature of
regexp strings makes it easy to make mistakes.  Just look at the sheer
number of regexp mistakes uncovered in our code base by Mattias
Engdegård during the last year.  It isn't an accident.

> The amount of knowledge you need to remember, the amount of
> documentation you need to consult, is the same.

The rx notation is easier to read and interpret, at least for some,
and I submit leads to fewer mistakes.

So no, I don't agree that it is "just the habit", and nothing else.



^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: combining cond and let, to replace pcase.
  2023-11-19 12:16         ` Gerd Möllmann
@ 2023-11-19 13:21           ` Eli Zaretskii
  2023-11-19 13:32             ` Gerd Möllmann
  2023-11-19 16:03           ` Joost Kremers
  1 sibling, 1 reply; 342+ messages in thread
From: Eli Zaretskii @ 2023-11-19 13:21 UTC (permalink / raw)
  To: Gerd Möllmann; +Cc: michael_heerdegen, rms, sbaugh, emacs-devel

> From: Gerd Möllmann <gerd.moellmann@gmail.com>
> Cc: Michael Heerdegen <michael_heerdegen@web.de>,  rms@gnu.org,
>  sbaugh@janestreet.com,  emacs-devel@gnu.org
> Date: Sun, 19 Nov 2023 13:16:58 +0100
> 
> But to the full truth also belongs that Richard has stopped programming
> completely in 2008

'git log --author="rms@gnu.org" --pretty=format:"%an%x09%ad%x09%s"'
begs to differ, FWIW.

> and that he doesn't seem to be very familiar with current Elisp

?? How is "current ELisp" different from 2008-vintage ELisp?



^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: combining cond and let, to replace pcase.
  2023-11-19 13:21           ` Eli Zaretskii
@ 2023-11-19 13:32             ` Gerd Möllmann
  2023-11-19 14:41               ` Eli Zaretskii
  0 siblings, 1 reply; 342+ messages in thread
From: Gerd Möllmann @ 2023-11-19 13:32 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: michael_heerdegen, rms, sbaugh, emacs-devel

Eli Zaretskii <eliz@gnu.org> writes:

>> From: Gerd Möllmann <gerd.moellmann@gmail.com>
>> Cc: Michael Heerdegen <michael_heerdegen@web.de>,  rms@gnu.org,
>>  sbaugh@janestreet.com,  emacs-devel@gnu.org
>> Date: Sun, 19 Nov 2023 13:16:58 +0100
>> 
>> But to the full truth also belongs that Richard has stopped programming
>> completely in 2008
>
> 'git log --author="rms@gnu.org" --pretty=format:"%an%x09%ad%x09%s"'
> begs to differ, FWIW.

I was remembering some interview I read on the Internet, which I can't
find anymore. Anyway, https://stallman.org/stallman-computing.html seems
to say some similar:

  My favorite programming languages are Lisp and C. However, since around
  1992 I have worked mainly on free software activism, which means I am
  too busy to do much programming. Around 2008 I stopped doing programming
  projects. As a result, I have not had time or occasion to learn newer
  languages such as Perl, Python, PHP, Ruby, Lua, Go, Scala, Rust, and so
  on. Therefore, I don't have an opinion about them as languages.

>> and that he doesn't seem to be very familiar with current Elisp
>
> ?? How is "current ELisp" different from 2008-vintage ELisp?

CLOS, generalized variables, pcase, apparently, I don't know.



^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: Instead of pcase
  2023-11-18  3:04           ` Richard Stallman
  2023-11-19 12:23             ` Michael Heerdegen
@ 2023-11-19 13:49             ` Dmitry Gutov
  2023-11-21  2:42               ` Richard Stallman
  1 sibling, 1 reply; 342+ messages in thread
From: Dmitry Gutov @ 2023-11-19 13:49 UTC (permalink / raw)
  To: rms, Philip Kaludercic; +Cc: emacs-devel

On 18/11/2023 05:04, Richard Stallman wrote:
>          > (`(,_ . ,(and (pred functionp) f)) (funcall f))
>          > (`(,hookfun . (,start ,end ,collection . ,plist))
> 
> I read the Info documentation of pcase a few days ago and I can't
> recall the rules for understanding those two pcase clauses.  What I
> recall is that they are not to be interpreted as Lisp expressions.
> They contain code that looks like Lisp but does not have the same
> semantic rules as Lisp.

Yes: it's a domain-specific language.

To interpret those backquotes and commas, one can imagine that the they 
do the inverse of the usual.

If normally you have commas to insert the values from the environment 
(variables or expressions) into the backquoted form, then inside pcase 
they are used to do the opposite: to extract values from the expression 
at given positions, and bind them with given names in the corresponding 
clause's environment.

I think that's pretty clever, but also quite readable once you "grok" 
the above idea.



^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: combining cond and let, to replace pcase.
  2023-11-19 13:08           ` Eli Zaretskii
@ 2023-11-19 13:52             ` Michael Heerdegen
  2023-11-19 14:45               ` Eli Zaretskii
  2023-11-19 13:59             ` Dmitry Gutov
  1 sibling, 1 reply; 342+ messages in thread
From: Michael Heerdegen @ 2023-11-19 13:52 UTC (permalink / raw)
  To: emacs-devel

Eli Zaretskii <eliz@gnu.org> writes:

> So we agree.  Then arguments about how easy pcase is for some are not
> relevant, because this is not what this is about, right?

It is a part of the picture.  How many these "some" are is another part.
And how harder it will become for those others to work with an
alternative tool is again another part.

And why is it always suggested that people not liking pcase are the norm
and those understanding it well are the deviation from the norm?  We don't
know whether some different tool is actually easier to learn on average.
And we won't find a fair solution if we leave out half of the people.

> > This is an excellent analogy.  Which one is the counterpart to `pcase'?
> > `rx' or the string form?
>
> The string, of course.

Interesting.  `rx' is more similar to pcase in some regards - it's
extensible with macro definitions (rx-defmacro), has descendants (even
more macros: rx-let) and adds syntax to the language that is not Lisp.

> It isn't only that.  It is also that the obscure and subtle nature of
> regexp strings makes it easy to make mistakes.  Just look at the sheer
> number of regexp mistakes uncovered in our code base by Mattias
> Engdegård during the last year.  It isn't an accident.

We have converters to convert between the two representations.  Did we
look at mistakes that are typical for `rx' forms?  It would be trivial
that we find less mistakes in `rx' forms when we only have a small
number of them compared to string regexps.

> > The amount of knowledge you need to remember, the amount of
> > documentation you need to consult, is the same.
>
> The rx notation is easier to read and interpret, at least for some,
> and I submit leads to fewer mistakes.

Yes, for some.  For me, too, actually.  Whether it leads to fewer
mistakes I don't know, both representations are really directly
isomorphic in this case.

> So no, I don't agree that it is "just the habit", and nothing else.

Personally I hate it if I have to read string regexps.  But I guess some
of the pcase critics don't like `rx' and others don't like string
regexps.

It is also not trivial which of both leads to more programming errors,
and why.

It is not trivial that `pcase' is a larger hurdle than an alternative.

I'm not convinced this is not "just the habit" - but there seems a lot
of psychology involved here, too.


Michael.





^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: combining cond and let, to replace pcase.
  2023-11-19 13:08           ` Eli Zaretskii
  2023-11-19 13:52             ` Michael Heerdegen
@ 2023-11-19 13:59             ` Dmitry Gutov
  2023-11-19 14:49               ` Eli Zaretskii
  1 sibling, 1 reply; 342+ messages in thread
From: Dmitry Gutov @ 2023-11-19 13:59 UTC (permalink / raw)
  To: Eli Zaretskii, Michael Heerdegen; +Cc: emacs-devel

On 19/11/2023 15:08, Eli Zaretskii wrote:
>> Actually both and none, this is exactly the point I raised in my other
>> reply - both have exactly the same complexity, and it is totally
>> subjective and only habit which one you prefer.
> It isn't only that.  It is also that the obscure and subtle nature of
> regexp strings makes it easy to make mistakes.  Just look at the sheer
> number of regexp mistakes uncovered in our code base by Mattias
> Engdegård during the last year.  It isn't an accident.

pcase is much better guarded against programmer mistakes because in a 
lot of cases typos or misunderstandings will be highlighted by the 
byte-compiler (potentially, with flymake directly in the buffer, which I 
also recommend everyone to enable).

Both rx and string regexps aren't able to take advantage of such. 
Mattias's checker took a lot of steps toward the same functionality, but 
it's ultimately limited, e.g. because we don't annotate regexps any 
differently from strings in the code.



^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: Instead of pcase
  2023-11-19 12:50       ` Eli Zaretskii
@ 2023-11-19 14:05         ` Dmitry Gutov
  2023-11-19 14:41           ` Po Lu
  2023-11-19 14:52           ` Eli Zaretskii
  2023-11-19 14:14         ` Michael Heerdegen
  1 sibling, 2 replies; 342+ messages in thread
From: Dmitry Gutov @ 2023-11-19 14:05 UTC (permalink / raw)
  To: Eli Zaretskii, Michael Heerdegen; +Cc: luangruo, jporterbugs, rms, emacs-devel

On 19/11/2023 14:50, Eli Zaretskii wrote:
>> From: Michael Heerdegen<michael_heerdegen@web.de>
>> Cc: Jim Porter<jporterbugs@gmail.com>,rms@gnu.org,emacs-devel@gnu.org
>> Date: Sun, 19 Nov 2023 12:48:08 +0100
>>
>> What I don't like here in this discussion is that some people are not
>> willing to accept that other people make different experiences with the
>> same things.
> This goes both ways, you know.

The "other side" doesn't create threads with angry comments about the 
developers with opposing views writing lower-level verbose code 
(choo-choo trains, Joao called that), with calls to prohibit such practices.

OTOH, enacting a ban on particular abstractions will just about 
guarantee that certain kinds of features will not be implemented.



^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: Instead of pcase
  2023-11-19 12:50       ` Eli Zaretskii
  2023-11-19 14:05         ` Dmitry Gutov
@ 2023-11-19 14:14         ` Michael Heerdegen
  2023-11-19 15:09           ` Eli Zaretskii
  1 sibling, 1 reply; 342+ messages in thread
From: Michael Heerdegen @ 2023-11-19 14:14 UTC (permalink / raw)
  To: emacs-devel

Eli Zaretskii <eliz@gnu.org> writes:

> > What I don't like here in this discussion is that some people are not
> > willing to accept that other people make different experiences with the
> > same things.
>
> This goes both ways, you know.

Indeed.

I'm curious how an alternative could look like, actually.  But unless
such an alternative exists or is completely designed, it is only a claim
that it would lead to less mistakes and would be simpler.  And I doubt
it.

It would have to implement the same set of features, so it would be
quite as complex as `pcase'.  You would have to remember or look up more
or less the same things and details.  Maybe in a different mood (some
people less angry, others more).

And here the `rx' example and `pcase' are very similar: what the
programmer actually has to keep in mind is how the regexp matching
algorithm or the pattern matching algorithm works.  This part is still a
black box, you must learn the specification, independently from the
language used to specify the matchers.  How the result is interpreted is
always something you have to learn additionally.

In your example, actually, string regexps are the primitive, low level
language, `rx' is the higher level language, so it should lead to less
mistakes (your argument).  `pcase' is the extensible higher level
language for pattern matching, specifically designed for this purpose,
so it should be more suited and lead to less mistakes than more
primitive tools.

Has anyone counted how many mistakes were introduced by wrong pcase
pattern specifications, compared to more verbose re-formulations using
other tools?  If we don't do that, the discussion is still selective,
with other words, about preferences again.


Michael.




^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: Instead of pcase
  2023-11-19 11:48     ` Michael Heerdegen
  2023-11-19 12:50       ` Eli Zaretskii
@ 2023-11-19 14:29       ` Po Lu
  2023-11-20 15:20         ` Michael Heerdegen
  2023-11-20 15:29         ` Dmitry Gutov
  1 sibling, 2 replies; 342+ messages in thread
From: Po Lu @ 2023-11-19 14:29 UTC (permalink / raw)
  To: Michael Heerdegen; +Cc: Jim Porter, rms, emacs-devel

Michael Heerdegen <michael_heerdegen@web.de> writes:

> "abstruse language" - "singular experience" ...(?) - sorry, are we
> people having understood pcase in few minutes some kind of aliens,
> compared to the "normal people"?  Do we not count?  Because we are not
> loud and angry and outraged?

With all due respect, your experience is very singular.  Don't assume
that I haven't canvassed other people's experiences, both on the
Internet and off-line, methodically and anecdotally.

My organization largely comprises C programmers who use Emacs for
programming, as a means to an end rather than an end in itself.  Our two
sites centrally provision their own Emacs configurations to all users,
which incorporates a large corpus of code for editing and analyzing C
programs in accord with local practice.  Naturally, the existence of
this corpus demands that programmers be charged with its upkeep, and as
no position is set aside for such work, this responsibility devolves on
individuals almost at random.  This is a representative microcosm of the
wider Emacs userbase, I think: for most are not hobbyists, or even
employed programmers for whom programming is also an avocation, but men
working for salaries, with bills to pay and families to... you can
complete the rest of this trite description.  And it is they whom I
canvassed.

I sent a poll to 34 individuals, all in some capacity involved in the
maintenance of Emacs Lisp.  Some of the questions asked were:

  - Have you previously read the documentation for pcase and cl-loop?

  - (If you haven't, read it now.)  Is the documentation for the pcase
    feature easily grasped, from your perspective?

  - Is the documentation for cl-loop easily grasped, from your
    perspective?

  - Read the pcase form in completion-at-point at
    /usr/src/[...]/simple.el.  Do you understand the variables that are
    bound, and the circumstances in which they are?

  - Read each cl-loop form in comp.el.  Could you rewrite those you
    understand with other constructs?

  - Do you think liberal use of cl-lib and pcase hinders the
    understanding of Emacs's own source code?

  - Do you think Emacs Lisp, excluding cl-lib and pcase, is wanting in
    list iteration or destructing constructs?

"Easily" refers also to whether you can learn the construct within an
amount of time that does not impact your work, not just whether it is
possible to learn with mechanical ease.

20 of the 34 answered yes to the first question, 5 of 34 to the second,
4 of 34 to the third, 12 of 34 to the fourth, 30 of 34 to the fifth, 30
to the sixth, and 6 to the seventh.  So I'd say the results were a
resounding vindication of all that I've maintained thus far.  There were
other items on the poll, but they related to our own policy for Emacs
Lisp and are by the by.

As regards experiences on the Internet, they are laid bare for all to
see.  In this thread, for starters.

> Interesting would be to hear concrete arguments, but we heard nearly
> none.  "I'm angry" is not an argument.

No one in this thread has been presenting indignation as an argument.



^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: Instead of pcase
  2023-11-19 14:05         ` Dmitry Gutov
@ 2023-11-19 14:41           ` Po Lu
  2023-11-19 14:44             ` Dmitry Gutov
  2023-11-19 14:52           ` Eli Zaretskii
  1 sibling, 1 reply; 342+ messages in thread
From: Po Lu @ 2023-11-19 14:41 UTC (permalink / raw)
  To: Dmitry Gutov
  Cc: Eli Zaretskii, Michael Heerdegen, jporterbugs, rms, emacs-devel

Dmitry Gutov <dmitry@gutov.dev> writes:

> OTOH, enacting a ban on particular abstractions will just about
> guarantee that certain kinds of features will not be implemented.

Not true.  Maybe some individuals will be thus disinclined to, but even
that's up for debate.



^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: combining cond and let, to replace pcase.
  2023-11-19 13:32             ` Gerd Möllmann
@ 2023-11-19 14:41               ` Eli Zaretskii
  2023-11-19 15:27                 ` Gerd Möllmann
  0 siblings, 1 reply; 342+ messages in thread
From: Eli Zaretskii @ 2023-11-19 14:41 UTC (permalink / raw)
  To: Gerd Möllmann; +Cc: michael_heerdegen, rms, sbaugh, emacs-devel

> From: Gerd Möllmann <gerd.moellmann@gmail.com>
> Cc: michael_heerdegen@web.de,  rms@gnu.org,  sbaugh@janestreet.com,
>   emacs-devel@gnu.org
> Date: Sun, 19 Nov 2023 14:32:25 +0100
> 
> Eli Zaretskii <eliz@gnu.org> writes:
> 
> >> But to the full truth also belongs that Richard has stopped programming
> >> completely in 2008
> >
> > 'git log --author="rms@gnu.org" --pretty=format:"%an%x09%ad%x09%s"'
> > begs to differ, FWIW.
> 
> I was remembering some interview I read on the Internet, which I can't
> find anymore. Anyway, https://stallman.org/stallman-computing.html seems
> to say some similar:
> 
>   My favorite programming languages are Lisp and C. However, since around
>   1992 I have worked mainly on free software activism, which means I am
>   too busy to do much programming. Around 2008 I stopped doing programming
>   projects. As a result, I have not had time or occasion to learn newer
>   languages such as Perl, Python, PHP, Ruby, Lua, Go, Scala, Rust, and so
>   on. Therefore, I don't have an opinion about them as languages.

"...stopped doing programming PROJECTS" (emphasis mine).  That's not
the same as "stopped programming completely".  Yours truly, for
example, didn't do any programming project whatsoever.

> >> and that he doesn't seem to be very familiar with current Elisp
> >
> > ?? How is "current ELisp" different from 2008-vintage ELisp?
> 
> CLOS, generalized variables, pcase, apparently, I don't know.

We all are only starting to get to know these.



^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: Instead of pcase
  2023-11-19 14:41           ` Po Lu
@ 2023-11-19 14:44             ` Dmitry Gutov
  0 siblings, 0 replies; 342+ messages in thread
From: Dmitry Gutov @ 2023-11-19 14:44 UTC (permalink / raw)
  To: Po Lu; +Cc: Eli Zaretskii, Michael Heerdegen, jporterbugs, rms, emacs-devel

On 19/11/2023 16:41, Po Lu wrote:
> Dmitry Gutov<dmitry@gutov.dev>  writes:
> 
>> OTOH, enacting a ban on particular abstractions will just about
>> guarantee that certain kinds of features will not be implemented.
> Not true.  Maybe some individuals will be thus disinclined to, but even
> that's up for debate.

I'm speaking from experience.

And it's not an accident that GUI code, for example, is 
abstraction-heavy pretty much everywhere.



^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: combining cond and let, to replace pcase.
  2023-11-19 13:52             ` Michael Heerdegen
@ 2023-11-19 14:45               ` Eli Zaretskii
  2023-11-20 15:35                 ` Michael Heerdegen
  0 siblings, 1 reply; 342+ messages in thread
From: Eli Zaretskii @ 2023-11-19 14:45 UTC (permalink / raw)
  To: Michael Heerdegen; +Cc: emacs-devel

> From: Michael Heerdegen <michael_heerdegen@web.de>
> Date: Sun, 19 Nov 2023 14:52:31 +0100
> 
> And why is it always suggested that people not liking pcase are the norm
> and those understanding it well are the deviation from the norm?

Who and where suggested that?

[I snipped all the rest of your message because it just expresses your
opinions, and we already agreed that opinions differ on this.]



^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: combining cond and let, to replace pcase.
  2023-11-19 13:59             ` Dmitry Gutov
@ 2023-11-19 14:49               ` Eli Zaretskii
  2023-11-19 14:53                 ` Dmitry Gutov
  0 siblings, 1 reply; 342+ messages in thread
From: Eli Zaretskii @ 2023-11-19 14:49 UTC (permalink / raw)
  To: Dmitry Gutov; +Cc: michael_heerdegen, emacs-devel

> Date: Sun, 19 Nov 2023 15:59:46 +0200
> Cc: emacs-devel@gnu.org
> From: Dmitry Gutov <dmitry@gutov.dev>
> 
> On 19/11/2023 15:08, Eli Zaretskii wrote:
> >> Actually both and none, this is exactly the point I raised in my other
> >> reply - both have exactly the same complexity, and it is totally
> >> subjective and only habit which one you prefer.
> > It isn't only that.  It is also that the obscure and subtle nature of
> > regexp strings makes it easy to make mistakes.  Just look at the sheer
> > number of regexp mistakes uncovered in our code base by Mattias
> > Engdegård during the last year.  It isn't an accident.
> 
> pcase is much better guarded against programmer mistakes because in a 
> lot of cases typos or misunderstandings will be highlighted by the 
> byte-compiler (potentially, with flymake directly in the buffer, which I 
> also recommend everyone to enable).

When we review patches, we don't normally byte-compile the changes,
nor need to run flymake on it.  Usually, it's enough to read the code.
Having to use non-trivial tools (which means apply the changes, which
means use some scratch branch or something similar) is extra hurdle.
It also means patches cannot be easily reviewed if all you have is a
MUA, without a full-blown Emacs development environment.

IOW, it means extra requirements and restrictions, so it's a
disadvantage.  It raises the bar.



^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: Instead of pcase
  2023-11-19 14:05         ` Dmitry Gutov
  2023-11-19 14:41           ` Po Lu
@ 2023-11-19 14:52           ` Eli Zaretskii
  2023-11-19 14:58             ` Dmitry Gutov
  1 sibling, 1 reply; 342+ messages in thread
From: Eli Zaretskii @ 2023-11-19 14:52 UTC (permalink / raw)
  To: Dmitry Gutov; +Cc: michael_heerdegen, luangruo, jporterbugs, rms, emacs-devel

> Date: Sun, 19 Nov 2023 16:05:28 +0200
> Cc: luangruo@yahoo.com, jporterbugs@gmail.com, rms@gnu.org,
>  emacs-devel@gnu.org
> From: Dmitry Gutov <dmitry@gutov.dev>
> 
> On 19/11/2023 14:50, Eli Zaretskii wrote:
> >> From: Michael Heerdegen<michael_heerdegen@web.de>
> >> Cc: Jim Porter<jporterbugs@gmail.com>,rms@gnu.org,emacs-devel@gnu.org
> >> Date: Sun, 19 Nov 2023 12:48:08 +0100
> >>
> >> What I don't like here in this discussion is that some people are not
> >> willing to accept that other people make different experiences with the
> >> same things.
> > This goes both ways, you know.
> 
> The "other side" doesn't create threads with angry comments about the 
> developers with opposing views writing lower-level verbose code 
> (choo-choo trains, Joao called that), with calls to prohibit such practices.

I meant this very thread.  The very previous message, actually.

> OTOH, enacting a ban on particular abstractions will just about 
> guarantee that certain kinds of features will not be implemented.

That's a strawman: no one of those who set policies here suggested any
bans.  One should be able to post opinions for and against certain
coding styles without being accuse in mortal sins.



^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: combining cond and let, to replace pcase.
  2023-11-19 14:49               ` Eli Zaretskii
@ 2023-11-19 14:53                 ` Dmitry Gutov
  0 siblings, 0 replies; 342+ messages in thread
From: Dmitry Gutov @ 2023-11-19 14:53 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: michael_heerdegen, emacs-devel

On 19/11/2023 16:49, Eli Zaretskii wrote:
>> Date: Sun, 19 Nov 2023 15:59:46 +0200
>> Cc:emacs-devel@gnu.org
>> From: Dmitry Gutov<dmitry@gutov.dev>
>>
>> On 19/11/2023 15:08, Eli Zaretskii wrote:
>>>> Actually both and none, this is exactly the point I raised in my other
>>>> reply - both have exactly the same complexity, and it is totally
>>>> subjective and only habit which one you prefer.
>>> It isn't only that.  It is also that the obscure and subtle nature of
>>> regexp strings makes it easy to make mistakes.  Just look at the sheer
>>> number of regexp mistakes uncovered in our code base by Mattias
>>> Engdegård during the last year.  It isn't an accident.
>> pcase is much better guarded against programmer mistakes because in a
>> lot of cases typos or misunderstandings will be highlighted by the
>> byte-compiler (potentially, with flymake directly in the buffer, which I
>> also recommend everyone to enable).
> When we review patches, we don't normally byte-compile the changes,
> nor need to run flymake on it.  Usually, it's enough to read the code.
> Having to use non-trivial tools (which means apply the changes, which
> means use some scratch branch or something similar) is extra hurdle.
> It also means patches cannot be easily reviewed if all you have is a
> MUA, without a full-blown Emacs development environment.
> 
> IOW, it means extra requirements and restrictions, so it's a
> disadvantage.  It raises the bar.

When we don't run a patch through CI, or apply it locally, we can just 
as well miss typos in "simple" code (and have done that on many occasions).

That just puts the burden of testing code code and using flymake on the 
contributor (both good practices anyway).



^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: Instead of pcase
  2023-11-19 14:52           ` Eli Zaretskii
@ 2023-11-19 14:58             ` Dmitry Gutov
  2023-11-19 15:14               ` Eli Zaretskii
  2023-11-21  2:43               ` Richard Stallman
  0 siblings, 2 replies; 342+ messages in thread
From: Dmitry Gutov @ 2023-11-19 14:58 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: michael_heerdegen, luangruo, jporterbugs, rms, emacs-devel

On 19/11/2023 16:52, Eli Zaretskii wrote:
>> Date: Sun, 19 Nov 2023 16:05:28 +0200
>> Cc:luangruo@yahoo.com,jporterbugs@gmail.com,rms@gnu.org,
>>   emacs-devel@gnu.org
>> From: Dmitry Gutov<dmitry@gutov.dev>
>>
>> On 19/11/2023 14:50, Eli Zaretskii wrote:
>>>> From: Michael Heerdegen<michael_heerdegen@web.de>
>>>> Cc: Jim Porter<jporterbugs@gmail.com>,rms@gnu.org,emacs-devel@gnu.org
>>>> Date: Sun, 19 Nov 2023 12:48:08 +0100
>>>>
>>>> What I don't like here in this discussion is that some people are not
>>>> willing to accept that other people make different experiences with the
>>>> same things.
>>> This goes both ways, you know.
>> The "other side" doesn't create threads with angry comments about the
>> developers with opposing views writing lower-level verbose code
>> (choo-choo trains, Joao called that), with calls to prohibit such practices.
> I meant this very thread.  The very previous message, actually.

I don't see calls for prohibiting those implementation styles, in the 
previous messages, or anywhere. It would be impractical anyway.

>> OTOH, enacting a ban on particular abstractions will just about
>> guarantee that certain kinds of features will not be implemented.
> That's a strawman: no one of those who set policies here suggested any
> bans.  One should be able to post opinions for and against certain
> coding styles without being accuse in mortal sins.

No one is arguing about whether people are allowed to post opinions.

There have been a few calls for working toward dropping pcase or cl-lib 
from the Emacs core, however.



^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: Instead of pcase
  2023-11-19 14:14         ` Michael Heerdegen
@ 2023-11-19 15:09           ` Eli Zaretskii
  2023-11-20 14:52             ` Michael Heerdegen
  0 siblings, 1 reply; 342+ messages in thread
From: Eli Zaretskii @ 2023-11-19 15:09 UTC (permalink / raw)
  To: Michael Heerdegen; +Cc: emacs-devel

> From: Michael Heerdegen <michael_heerdegen@web.de>
> Date: Sun, 19 Nov 2023 15:14:58 +0100
> 
> I'm curious how an alternative could look like, actually.

I don't know.  So I withdraw my judgment until such an alternative is
presented.  I suggest that everyone do the same.

> It would have to implement the same set of features, so it would be
> quite as complex as `pcase'.

Complexity doesn't necessarily mean cryptic syntax.  Cf regexp strings
vs Rx.

Cryptic syntax raises the bar by adding one more obstacle: before you
deal with semantic complexity, you need to fight the uphill battle of
syntactic complexity and obscurity.

> You would have to remember or look up more or less the same things
> and details.

But if "the same things" speak for themselves, because they are
identified in more human-readable language, you have fewer things to
look up.  Again, cf. regexp strings vs Rx.

> And here the `rx' example and `pcase' are very similar: what the
> programmer actually has to keep in mind is how the regexp matching
> algorithm or the pattern matching algorithm works.

That's true, but before you consider the subtleties of matching, you
need to understand what the regexp should match, and that is harder
with regexp strings when advanced features are used.

> In your example, actually, string regexps are the primitive, low level
> language, `rx' is the higher level language, so it should lead to less
> mistakes (your argument).  `pcase' is the extensible higher level
> language for pattern matching, specifically designed for this purpose,
> so it should be more suited and lead to less mistakes than more
> primitive tools.

To me, whether stuff is lower or higher in level is less relevant
here.  For example, macros can be considered "higher-level" constructs
than the underlying Lisp functions and primitives, but macros are
harder to read due to the additional syntax: the backticks, the comma,
the @, etc.

I'd say that higher-level languages always make it easier to write
programs, but don't necessarily make it easier to read them.  As
another data point, consider the C preprocessor macros and
specifically their advanced features, like # and ##.  I invite you to
try reading what we have in src/conf_post.h and src/lisp.h, and make
up your own mind.

> Has anyone counted how many mistakes were introduced by wrong pcase
> pattern specifications, compared to more verbose re-formulations using
> other tools?  If we don't do that, the discussion is still selective,
> with other words, about preferences again.

Should be good to do that, but please remember that pcase exists for
less than a decade, so we are just starting to learn to use it.



^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: Instead of pcase
  2023-11-19 14:58             ` Dmitry Gutov
@ 2023-11-19 15:14               ` Eli Zaretskii
  2023-11-19 18:04                 ` Dmitry Gutov
  2023-11-21  2:43               ` Richard Stallman
  1 sibling, 1 reply; 342+ messages in thread
From: Eli Zaretskii @ 2023-11-19 15:14 UTC (permalink / raw)
  To: Dmitry Gutov; +Cc: michael_heerdegen, luangruo, jporterbugs, rms, emacs-devel

> Date: Sun, 19 Nov 2023 16:58:39 +0200
> Cc: michael_heerdegen@web.de, luangruo@yahoo.com, jporterbugs@gmail.com,
>  rms@gnu.org, emacs-devel@gnu.org
> From: Dmitry Gutov <dmitry@gutov.dev>
> 
> On 19/11/2023 16:52, Eli Zaretskii wrote:
> >>>>
> >>>> What I don't like here in this discussion is that some people are not
> >>>> willing to accept that other people make different experiences with the
> >>>> same things.
> >>> This goes both ways, you know.
> >> The "other side" doesn't create threads with angry comments about the
> >> developers with opposing views writing lower-level verbose code
> >> (choo-choo trains, Joao called that), with calls to prohibit such practices.
> > I meant this very thread.  The very previous message, actually.
> 
> I don't see calls for prohibiting those implementation styles, in the 
> previous messages, or anywhere. It would be impractical anyway.

I wasn't talking about prohibiting, I was talking about accepting that
both sides have a right to describe their experiences.

> >> OTOH, enacting a ban on particular abstractions will just about
> >> guarantee that certain kinds of features will not be implemented.
> > That's a strawman: no one of those who set policies here suggested any
> > bans.  One should be able to post opinions for and against certain
> > coding styles without being accuse in mortal sins.
> 
> No one is arguing about whether people are allowed to post opinions.
> 
> There have been a few calls for working toward dropping pcase or cl-lib 
> from the Emacs core, however.

You need to know to whom you listen, before you make such far-reaching
conclusions.



^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: combining cond and let, to replace pcase.
  2023-11-19 14:41               ` Eli Zaretskii
@ 2023-11-19 15:27                 ` Gerd Möllmann
  2023-11-19 15:29                   ` Eli Zaretskii
  0 siblings, 1 reply; 342+ messages in thread
From: Gerd Möllmann @ 2023-11-19 15:27 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: michael_heerdegen, rms, sbaugh, emacs-devel

Eli Zaretskii <eliz@gnu.org> writes:

>>   My favorite programming languages are Lisp and C. However, since around
>>   1992 I have worked mainly on free software activism, which means I am
>>   too busy to do much programming. Around 2008 I stopped doing programming
>>   projects. As a result, I have not had time or occasion to learn newer
>>   languages such as Perl, Python, PHP, Ruby, Lua, Go, Scala, Rust, and so
>>   on. Therefore, I don't have an opinion about them as languages.
>
> "...stopped doing programming PROJECTS" (emphasis mine).  That's not
> the same as "stopped programming completely".  Yours truly, for
> example, didn't do any programming project whatsoever.

Ok, but it also says before that "which means I am too busy to do much
programming" (since 1992). I guess what that means when combined with
the later "since 2008" in open to interpretation.

What I really meant to say with all this, is that I find doubting a
premise is always a good thing. There is more to a given su.bject than
what a person has done in the past. I myself, for example, can generally
not be trusted. People should always use their own brain.


BTW, since you mention it, I've been programming the whole time, until
recently, partially because of age. I worked in commercial projects, as
a freelance programmer.

No Emacs at all, that is 100% true. Not even as a user, for the most
time, since say 2004, I don't know.

And I'm still not doing much, partially because no-one wanted it (C++,
CL packages (kind of there, but rotting)), and partially because I've
realized that meanwhile things qre too big for me (concurrent
redisplay).

But I've done sometihing. Adding packages to Elisp leads one to a lot of
strange places :-).

However, despite the long absence, in the 1.5 or so that I've picked up
Emacs again, and did stuff, I never had any problems understanding
things. Which makes what's going on so perplexing.



^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: combining cond and let, to replace pcase.
  2023-11-19 15:27                 ` Gerd Möllmann
@ 2023-11-19 15:29                   ` Eli Zaretskii
  0 siblings, 0 replies; 342+ messages in thread
From: Eli Zaretskii @ 2023-11-19 15:29 UTC (permalink / raw)
  To: Gerd Möllmann; +Cc: michael_heerdegen, rms, sbaugh, emacs-devel

> From: Gerd Möllmann <gerd.moellmann@gmail.com>
> Cc: michael_heerdegen@web.de,  rms@gnu.org,  sbaugh@janestreet.com,
>   emacs-devel@gnu.org
> Date: Sun, 19 Nov 2023 16:27:54 +0100
> 
> However, despite the long absence, in the 1.5 or so that I've picked up
> Emacs again, and did stuff, I never had any problems understanding
> things. Which makes what's going on so perplexing.

People are different.



^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: Instead of pcase
  2023-11-19 12:23             ` Michael Heerdegen
@ 2023-11-19 16:02               ` Barry Fishman
  2023-11-19 17:59                 ` Dmitry Gutov
  0 siblings, 1 reply; 342+ messages in thread
From: Barry Fishman @ 2023-11-19 16:02 UTC (permalink / raw)
  To: emacs-devel

On 2023-11-19 13:23:17 +01, Michael Heerdegen wrote:
> So, the advantage would be more of a psychological kind: you have normal
> Lisp function calls, but structurally you have the same thing, and you
> have to remember exactly the same set of details.  The complexity comes
> from the task, not from the implementation.

I submit that the opposite is true,  the complexity is in its
implementation, not the task.

In languages like Haskell this is expressed in a very simple way, so the
task is not in itself hard to understand.

For example, one implementation might be to use the form:

  (proto-case x
   (typeproto guard expressions...)
   ...)

The typeproto would be a type, or a list made up of the type and a
variable that could be use in the expression.

The guard would be an expression which is required to be true before a
match can be declared.

Composite types like pair, list, vector, or list*, would have typeproto's
for their arguments when they are expanded as a list):

  (proto-case x
    ((list string integer) t ...))

which would match a list of two element, the first a string, and the
second an integer.  The guard (t) would always consider it a match.

The list arguments which are typeproto's themselves, could be made into
assignments with using a list, as above.

If x is a list with its first element a string "foo" and the second an
integer, remove it from x and add the second element to total:

  (proto-case x
    ((list* (string name) (integer count) (t rest))
     (string-equal name "foo")
     (set! total (+ total count))
     (set! x rest)))

This is just one of many other ways one could setup a matching
expression in elisp, the best is a balance between implementation
efficiency and readability.

I think the complexity doesn't come from the task, but comes from the
choice of implementation.  So its the complexity of the implementation
that should determines whether it is worth while implementing.

Although back-quoting is part of Lisp, it was added to solve a specific
problem, and unfortunately added new syntax tokens to Lisp, which it
otherwise avoids.

-- 
Barry Fishman




^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: combining cond and let, to replace pcase.
  2023-11-19 12:16         ` Gerd Möllmann
  2023-11-19 13:21           ` Eli Zaretskii
@ 2023-11-19 16:03           ` Joost Kremers
  2023-11-19 16:59             ` Eli Zaretskii
  1 sibling, 1 reply; 342+ messages in thread
From: Joost Kremers @ 2023-11-19 16:03 UTC (permalink / raw)
  To: emacs-devel; +Cc: Eli Zaretskii, Michael Heerdegen, rms, Gerd Möllmann


On Sun, Nov 19 2023, Gerd Möllmann wrote:
> But to the full truth also belongs that Richard has stopped programming
> completely in 2008, says he himself, and that he doesn't seem to be very
> familiar with current Elisp, if he's seen pcase for the first time a few
> days ago. One must keep that in mind.

Actually, it's not the first time Richard has seen pcase. There was a very
similar thread to this one in 2018, where he asked about pcase. See e.g.,
<https://lists.gnu.org/archive/html/emacs-devel/2018-10/msg00440.html>:

```
  > In what sense is the above cl-case more clear than the pcase equivalent?
  > I'm not saying the pcase version is better in those cases, but I think
  > the respective advantages and disadvantages pretty much balance out.

I also wonder.  Is it simply that people find pcase unfamiliar?
```

I wrote a somewhat lengthy reply to that message trying to pinpoint the things
that I found unintuitive (read: unfamiliar) about pcase's syntax. I won't repeat
the whole thing here (the message can be found here:
https://lists.gnu.org/archive/html/emacs-devel/2018-10/msg00448.html). The gist
of it is that pcase uses a couple of syntax elements that *look* familiar but
don't have their familiar meaning.

That has actually been said in this thread before, so that's no revelation. I do
think the documentation could be improved, however, if it were (re?)written with
that aspect in mind. Or perhaps it would be better to add an introductory
section explaining those aspects.

I'd be willing to give it a shot, BTW, if there's interest. No promise on an
ETA, but I should have some spare time in the coming weeks.


-- 
Joost Kremers
Life has its moments



^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: combining cond and let, to replace pcase.
  2023-11-18  3:03   ` combining cond and let, to replace pcase Richard Stallman
  2023-11-19 11:20     ` Michael Heerdegen
@ 2023-11-19 16:08     ` Axel Forsman
  2023-11-21 15:53     ` Michael Heerdegen
  2023-11-23  2:58     ` Richard Stallman
  3 siblings, 0 replies; 342+ messages in thread
From: Axel Forsman @ 2023-11-19 16:08 UTC (permalink / raw)
  To: rms; +Cc: Spencer Baugh, emacs-devel

Richard Stallman <rms@gnu.org> writes:

>   > I've thought before that it would be nice to have a cond-let construct,
>   > like if-let and when-let.
>
> Here's an example to show what I have come up with along these lines:
>
> (cond* (:bind (x foobar) y z (foo 5) a)  ;; variables to bind, as in let
>        ;; I'm also thinking of using nil instead of :bind.
>
>        ;; t as condition means run this clause unconditionally
>        ;; then continue with next clause.
>        (t do-this-unconditionally-and-dont-stop...)
>
>        ;; Tests with a new function `match' which I'm going to work on next.
>        ((match x 'foo) ...)
>
>        ;; t in the last clause means the same as in previous clauses,
>        ;; but you can think of it as being the same as in `cond'.
>        (t do-this-as-last-resort)
>        )
>
> Rhe idea is that conf* does part of pcase's added functionality, and
> `match' will do the rest.  But it is not necessary to cram _all_ the
> additional matching functionality (to compare to pcase) into a single
> new function. 
>
> We could have more than one new function, eacn for its own kind of
> pattern matching.
>
> Some of them could do destructuring as well as matching.

pcase is not concerned with your proposed :bind and t keywords. For a
discussion about pcase being too "large", it seems weird to suggest an
alternative that does even more. What am I missing?

Also, the various `match' constructs would have to be part of the conf*
macro as destructuring needs to bind variables, so I fail to see how
this would be an improvement over the status quo?

I may be misinterpreting what you are proposing here, and in that case I
apologize, but in general should one not try to understand the thing
they are attempting to replace, or else likely make the same mistakes?

> I hoipe that using a few constructs to divide up the job will avoid
> the kludginess of pcase's bells-and-whistles-for-everything approach,
> resulting in something equally convenient but made of simple components.

I will preface this by saying that I like pcase, I think it is one of
the better-written Emacs Lisp packages. History has shown that
declarative pattern matching à la ML is a good concept, with languages
on the "other side of the pond" such as Java; Python; C++; JavaScript;
and C#, all eventually adopting it. Any discussion about the purported
complexity of pcase should start with delineating the essentials of
pcase, (something I do not think this mailing thread has done a good job
of), which is that the pcase syntax for destructuring a value should
mirror the syntax for constructing that same value. E.g.

    `(if ,condition ,consequent ,alternative)

constructs a list if condition, consequent, and alternative are
variables currently bound, and is also a pcase pattern for
deconstructing that same list. IMO that is perfectly simple.

Does the addition of other pcase pattern-forms such as
pred/app/guard/and/or complicate things too much? I would say maybe;
it is certainly possible to abuse them.

On the other hand, it is very useful to match against an integer in some
range, nested withing a list, e.g.

    (pcase x
      (`(integer ,(and (pred (lambda (i) (< 0 i 5))) i)) (print i))
      (`(integer ,i) (do-something-else i))
      ...)

From what I have seen from languages that do not have special syntax for
matching integers in ranges, this would usually be handled by guard
expressions as a second step after matching is done, e.g.

    (pcase x
      (`(integer ,i) :when (< 0 i 5)
        (print i))
      (`(integer ,i) (do-something-else i))
      ...)

Something like that would work to keep the patterns simpler.

Without pred/app/guard/and/or one could think of getting rid of the
messy backquote/comma syntax, for something cleaner based just on lists,
e.g.

    (pcase x
      (('integer i) (print i))
      (('if condition consequent alternative) (message "if"))
      ...)

however that would not good for a couple of reasons:

1. The syntax for constructing lists is no longer the same as for
   destructuring.
2. It would leave little room for incorporating syntax for destructuring
   cl-struct:s, etc. pcase has the (cl-struct TYPE &rest FIELDS) form
   for this purpose, which is what it is, but at least I think it is
   good that it exists.

This is all to say that I disagree with your claim that pcase has a
bells-and-whistles-for-everything approach. Rather it is maximally
compositional and based on the easy-to-learn and neat duality of
constructing/destructuring.
I also consider it a mistake to introduce forms such as

>        ;; t as condition means run this clause unconditionally
>        ;; then continue with next clause.
>        (t do-this-unconditionally-and-dont-stop...)

with non-descriptive names such as nil/t, that introduce side-effects in
the middle of matching something. Pattern matching is great because it
is declarative and makes it possible to communicate intent, rather than
concerning ourselves with what combination of car/cdr/equal/let/if is
needed to achieve what we want.



^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: combining cond and let, to replace pcase.
  2023-11-19 16:03           ` Joost Kremers
@ 2023-11-19 16:59             ` Eli Zaretskii
  2023-11-19 18:29               ` Joost Kremers
  0 siblings, 1 reply; 342+ messages in thread
From: Eli Zaretskii @ 2023-11-19 16:59 UTC (permalink / raw)
  To: Joost Kremers; +Cc: emacs-devel, michael_heerdegen, rms, gerd.moellmann

> From: Joost Kremers <joostkremers@fastmail.fm>
> Cc: Eli Zaretskii <eliz@gnu.org>, Michael Heerdegen
>  <michael_heerdegen@web.de>, rms@gnu.org, Gerd Möllmann
>  <gerd.moellmann@gmail.com>
> Date: Sun, 19 Nov 2023 17:03:25 +0100
> 
> That has actually been said in this thread before, so that's no revelation. I do
> think the documentation could be improved, however, if it were (re?)written with
> that aspect in mind. Or perhaps it would be better to add an introductory
> section explaining those aspects.
> 
> I'd be willing to give it a shot, BTW, if there's interest. No promise on an
> ETA, but I should have some spare time in the coming weeks.

There's always interest in improving the documentation.  So from where
I stand, please feel free to suggest such improvements.  But please
note that there are several different methodological approaches to
documenting pcase, which already caused in the past quite a bit of
arguments about what and how to say there.  So please don't feel
offended if you hear some objections to portions of what you post when
you post it.

TIA



^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: Instead of pcase
  2023-11-19 16:02               ` Barry Fishman
@ 2023-11-19 17:59                 ` Dmitry Gutov
  2023-11-19 19:31                   ` Eric Abrahamsen
  2023-11-19 21:15                   ` Barry Fishman
  0 siblings, 2 replies; 342+ messages in thread
From: Dmitry Gutov @ 2023-11-19 17:59 UTC (permalink / raw)
  To: Barry Fishman, emacs-devel

On 19/11/2023 18:02, Barry Fishman wrote:
> On 2023-11-19 13:23:17 +01, Michael Heerdegen wrote:
>> So, the advantage would be more of a psychological kind: you have normal
>> Lisp function calls, but structurally you have the same thing, and you
>> have to remember exactly the same set of details.  The complexity comes
>> from the task, not from the implementation.
> 
> I submit that the opposite is true,  the complexity is in its
> implementation, not the task.
> 
> In languages like Haskell this is expressed in a very simple way, so the
> task is not in itself hard to understand.

Haskell is notable for using the same (or similar) syntax for 
destructuring as it uses for constructing expressions.

pcase actually follows that practice with backquotes and commas.

And in both matching and destructuring are done in the same expression 
(the presence of the latter is determined by whether a pattern contains 
variable bindindgs).

> If x is a list with its first element a string "foo" and the second an
> integer, remove it from x and add the second element to total:
> 
>    (proto-case x
>      ((list* (string name) (integer count) (t rest))
>       (string-equal name "foo")
>       (set! total (+ total count))
>       (set! x rest)))
> 
> This is just one of many other ways one could setup a matching
> expression in elisp, the best is a balance between implementation
> efficiency and readability.

And this divorces matching from destructuring. I suggest you try 
rewriting one of the more complex pcase usages into this syntax and see 
what people think of the result.



^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: Instead of pcase
  2023-11-19 15:14               ` Eli Zaretskii
@ 2023-11-19 18:04                 ` Dmitry Gutov
  2023-11-19 18:30                   ` Eli Zaretskii
  0 siblings, 1 reply; 342+ messages in thread
From: Dmitry Gutov @ 2023-11-19 18:04 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: michael_heerdegen, luangruo, jporterbugs, rms, emacs-devel

On 19/11/2023 17:14, Eli Zaretskii wrote:
>> Date: Sun, 19 Nov 2023 16:58:39 +0200
>> Cc: michael_heerdegen@web.de, luangruo@yahoo.com, jporterbugs@gmail.com,
>>   rms@gnu.org, emacs-devel@gnu.org
>> From: Dmitry Gutov <dmitry@gutov.dev>
>>
>> On 19/11/2023 16:52, Eli Zaretskii wrote:
>>>>>>
>>>>>> What I don't like here in this discussion is that some people are not
>>>>>> willing to accept that other people make different experiences with the
>>>>>> same things.
>>>>> This goes both ways, you know.
>>>> The "other side" doesn't create threads with angry comments about the
>>>> developers with opposing views writing lower-level verbose code
>>>> (choo-choo trains, Joao called that), with calls to prohibit such practices.
>>> I meant this very thread.  The very previous message, actually.
>>
>> I don't see calls for prohibiting those implementation styles, in the
>> previous messages, or anywhere. It would be impractical anyway.
> 
> I wasn't talking about prohibiting, I was talking about accepting that
> both sides have a right to describe their experiences.

Perhaps you'll consider posting a message supporting both positions, then.

>>>> OTOH, enacting a ban on particular abstractions will just about
>>>> guarantee that certain kinds of features will not be implemented.
>>> That's a strawman: no one of those who set policies here suggested any
>>> bans.  One should be able to post opinions for and against certain
>>> coding styles without being accuse in mortal sins.
>>
>> No one is arguing about whether people are allowed to post opinions.
>>
>> There have been a few calls for working toward dropping pcase or cl-lib
>> from the Emacs core, however.
> 
> You need to know to whom you listen, before you make such far-reaching
> conclusions.

I don't think I've made any specific conclusion (or any predictions).

But when some prolific contributors make such statements, and RMS is 
noticeably on their side, that can't help but create a certain 
impression to the public (this list is read not just by the core 
contributors).



^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: combining cond and let, to replace pcase.
  2023-11-19 11:20     ` Michael Heerdegen
  2023-11-19 11:43       ` Eli Zaretskii
  2023-11-19 12:04       ` Gerd Möllmann
@ 2023-11-19 18:10       ` Tomas Hlavaty
  2023-11-25  4:45         ` Stefan Monnier via Emacs development discussions.
  2023-11-19 21:36       ` Alan Mackenzie
  3 siblings, 1 reply; 342+ messages in thread
From: Tomas Hlavaty @ 2023-11-19 18:10 UTC (permalink / raw)
  To: Michael Heerdegen, Richard Stallman; +Cc: Spencer Baugh, emacs-devel

On Sun 19 Nov 2023 at 12:20, Michael Heerdegen <michael_heerdegen@web.de> wrote:
> Richard Stallman <rms@gnu.org> writes:
>
>> Some of them could do destructuring as well as matching.
>>
>> I hoipe that using a few constructs to divide up the job will avoid
>> the kludginess of pcase's bells-and-whistles-for-everything approach,
>> resulting in something equally convenient but made of simple
>> components.
>
> I really don't know how you come to such a conclusion.
[...]
> To me this discussion looks like some people aren't willing to accept
> multiplication like 10*5 because it "looks strange" and "one would rather
> write "5+5+5+5+5+5+5+5+5+5" because this would be much simpler and we
> don't need this strange "*" at all.

no, one would rather write (* 10 5)

and (+ 5 (* 3 2) 1) than 5+3*2+1

instead of a form with complex syntax, e.g. have * and + functions
instead of infix macro

that is why cl-loop and maybe pcase are "ugly"

one heuristic could be if autodoc can display something useful



^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: combining cond and let, to replace pcase.
  2023-11-19 16:59             ` Eli Zaretskii
@ 2023-11-19 18:29               ` Joost Kremers
  2023-11-19 18:35                 ` Eli Zaretskii
  0 siblings, 1 reply; 342+ messages in thread
From: Joost Kremers @ 2023-11-19 18:29 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: emacs-devel


On Sun, Nov 19 2023, Eli Zaretskii wrote:
> There's always interest in improving the documentation.  So from where
> I stand, please feel free to suggest such improvements.  But please
> note that there are several different methodological approaches to
> documenting pcase, which already caused in the past quite a bit of
> arguments about what and how to say there.  So please don't feel
> offended if you hear some objections to portions of what you post when
> you post it.

No worries, I've been lurking here long enough to know that brutal honesty is
the modus operandi of this list. :D

I can really only write what I think I would have found helpful at the time.
Whether it's suitable for inclusion or not is for others to decide.

-- 
Joost Kremers
Life has its moments



^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: Instead of pcase
  2023-11-19 18:04                 ` Dmitry Gutov
@ 2023-11-19 18:30                   ` Eli Zaretskii
  2023-11-19 18:51                     ` Dmitry Gutov
  0 siblings, 1 reply; 342+ messages in thread
From: Eli Zaretskii @ 2023-11-19 18:30 UTC (permalink / raw)
  To: Dmitry Gutov; +Cc: michael_heerdegen, luangruo, jporterbugs, rms, emacs-devel

> Date: Sun, 19 Nov 2023 20:04:56 +0200
> Cc: michael_heerdegen@web.de, luangruo@yahoo.com, jporterbugs@gmail.com,
>  rms@gnu.org, emacs-devel@gnu.org
> From: Dmitry Gutov <dmitry@gutov.dev>
> 
> >> I don't see calls for prohibiting those implementation styles, in the
> >> previous messages, or anywhere. It would be impractical anyway.
> > 
> > I wasn't talking about prohibiting, I was talking about accepting that
> > both sides have a right to describe their experiences.
> 
> Perhaps you'll consider posting a message supporting both positions, then.

I don't understand what you mean by "supporting both positions".  How
is it possible for a person to support two opposite positions?

> >>>> OTOH, enacting a ban on particular abstractions will just about
> >>>> guarantee that certain kinds of features will not be implemented.
> >>> That's a strawman: no one of those who set policies here suggested any
> >>> bans.  One should be able to post opinions for and against certain
> >>> coding styles without being accuse in mortal sins.
> >>
> >> No one is arguing about whether people are allowed to post opinions.
> >>
> >> There have been a few calls for working toward dropping pcase or cl-lib
> >> from the Emacs core, however.
> > 
> > You need to know to whom you listen, before you make such far-reaching
> > conclusions.
> 
> I don't think I've made any specific conclusion (or any predictions).

So your reference to "enacting a ban" is not a conclusion?  Then why
are you condemning something about which you still didn't reach any
specific conclusions?

> But when some prolific contributors make such statements, and RMS is 
> noticeably on their side, that can't help but create a certain 
> impression to the public (this list is read not just by the core 
> contributors).

That impression is unjustified, and acting on it raises the level of
unnecessary flames, and is not otherwise useful in any way.



^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: combining cond and let, to replace pcase.
  2023-11-19 18:29               ` Joost Kremers
@ 2023-11-19 18:35                 ` Eli Zaretskii
  0 siblings, 0 replies; 342+ messages in thread
From: Eli Zaretskii @ 2023-11-19 18:35 UTC (permalink / raw)
  To: Joost Kremers; +Cc: emacs-devel

> From: Joost Kremers <joostkremers@fastmail.fm>
> Cc: emacs-devel@gnu.org
> Date: Sun, 19 Nov 2023 19:29:49 +0100
> 
> I can really only write what I think I would have found helpful at the time.
> Whether it's suitable for inclusion or not is for others to decide.

SGTM, TIA.



^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: Instead of pcase
  2023-11-19 18:30                   ` Eli Zaretskii
@ 2023-11-19 18:51                     ` Dmitry Gutov
  2023-11-19 19:49                       ` Eli Zaretskii
  0 siblings, 1 reply; 342+ messages in thread
From: Dmitry Gutov @ 2023-11-19 18:51 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: michael_heerdegen, luangruo, jporterbugs, rms, emacs-devel

On 19/11/2023 20:30, Eli Zaretskii wrote:
>> Date: Sun, 19 Nov 2023 20:04:56 +0200
>> Cc: michael_heerdegen@web.de, luangruo@yahoo.com, jporterbugs@gmail.com,
>>   rms@gnu.org, emacs-devel@gnu.org
>> From: Dmitry Gutov <dmitry@gutov.dev>
>>
>>>> I don't see calls for prohibiting those implementation styles, in the
>>>> previous messages, or anywhere. It would be impractical anyway.
>>>
>>> I wasn't talking about prohibiting, I was talking about accepting that
>>> both sides have a right to describe their experiences.
>>
>> Perhaps you'll consider posting a message supporting both positions, then.
> 
> I don't understand what you mean by "supporting both positions".  How
> is it possible for a person to support two opposite positions?

For example:

   I understand you guys and you guys, but we're not going to do any
   major changes (for the usual compatibility reasons, for example),
   though we would consider some minor improvements if either of you
   can suggest any.

>>>>>> OTOH, enacting a ban on particular abstractions will just about
>>>>>> guarantee that certain kinds of features will not be implemented.
>>>>> That's a strawman: no one of those who set policies here suggested any
>>>>> bans.  One should be able to post opinions for and against certain
>>>>> coding styles without being accuse in mortal sins.
>>>>
>>>> No one is arguing about whether people are allowed to post opinions.
>>>>
>>>> There have been a few calls for working toward dropping pcase or cl-lib
>>>> from the Emacs core, however.
>>>
>>> You need to know to whom you listen, before you make such far-reaching
>>> conclusions.
>>
>> I don't think I've made any specific conclusion (or any predictions).
> 
> So your reference to "enacting a ban" is not a conclusion?  Then why
> are you condemning something about which you still didn't reach any
> specific conclusions?

I haven't made any predictions or conclusions as to whether a ban is 
forthcoming.

Sometimes it helps to anticipate any such action, though, for example 
because many leaders feel it difficult to change position once a public 
declaration has been made.

>> But when some prolific contributors make such statements, and RMS is
>> noticeably on their side, that can't help but create a certain
>> impression to the public (this list is read not just by the core
>> contributors).
> 
> That impression is unjustified, and acting on it raises the level of
> unnecessary flames, and is not otherwise useful in any way.

I'd like to help avoid it being made, on various observers.



^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: Instead of pcase
  2023-11-19 17:59                 ` Dmitry Gutov
@ 2023-11-19 19:31                   ` Eric Abrahamsen
  2023-11-25  4:23                     ` Stefan Monnier via Emacs development discussions.
  2023-11-19 21:15                   ` Barry Fishman
  1 sibling, 1 reply; 342+ messages in thread
From: Eric Abrahamsen @ 2023-11-19 19:31 UTC (permalink / raw)
  To: emacs-devel

Dmitry Gutov <dmitry@gutov.dev> writes:

> On 19/11/2023 18:02, Barry Fishman wrote:
>> On 2023-11-19 13:23:17 +01, Michael Heerdegen wrote:
>>> So, the advantage would be more of a psychological kind: you have normal
>>> Lisp function calls, but structurally you have the same thing, and you
>>> have to remember exactly the same set of details.  The complexity comes
>>> from the task, not from the implementation.
>> I submit that the opposite is true,  the complexity is in its
>> implementation, not the task.
>> In languages like Haskell this is expressed in a very simple way, so
>> the
>> task is not in itself hard to understand.
>
> Haskell is notable for using the same (or similar) syntax for
> destructuring as it uses for constructing expressions.
>
> pcase actually follows that practice with backquotes and commas.
>
> And in both matching and destructuring are done in the same expression
> (the presence of the latter is determined by whether a pattern
> contains variable bindindgs).

+1, thanks for stating this so clearly in this and your earlier message.

I agree that once you introduce guards/predicates, pcase gets ugly fast,
but as you and Michael say, the core conceit is already as simple as it
could be, and is deeply consonant with the already-understood meaning of
the backquote.




^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: Instead of pcase
  2023-11-19 18:51                     ` Dmitry Gutov
@ 2023-11-19 19:49                       ` Eli Zaretskii
  0 siblings, 0 replies; 342+ messages in thread
From: Eli Zaretskii @ 2023-11-19 19:49 UTC (permalink / raw)
  To: Dmitry Gutov; +Cc: michael_heerdegen, luangruo, jporterbugs, rms, emacs-devel

> Date: Sun, 19 Nov 2023 20:51:37 +0200
> Cc: michael_heerdegen@web.de, luangruo@yahoo.com, jporterbugs@gmail.com,
>  rms@gnu.org, emacs-devel@gnu.org
> From: Dmitry Gutov <dmitry@gutov.dev>
> 
> >> Perhaps you'll consider posting a message supporting both positions, then.
> > 
> > I don't understand what you mean by "supporting both positions".  How
> > is it possible for a person to support two opposite positions?
> 
> For example:
> 
>    I understand you guys and you guys, but we're not going to do any
>    major changes (for the usual compatibility reasons, for example),
>    though we would consider some minor improvements if either of you
>    can suggest any.

How is this "supporting both positions"? which "both positions"?

Also, to which changes does the above allude?

> >>>>>> OTOH, enacting a ban on particular abstractions will just about
> >>>>>> guarantee that certain kinds of features will not be implemented.
> >>>>> That's a strawman: no one of those who set policies here suggested any
> >>>>> bans.  One should be able to post opinions for and against certain
> >>>>> coding styles without being accuse in mortal sins.
> >>>>
> >>>> No one is arguing about whether people are allowed to post opinions.
> >>>>
> >>>> There have been a few calls for working toward dropping pcase or cl-lib
> >>>> from the Emacs core, however.
> >>>
> >>> You need to know to whom you listen, before you make such far-reaching
> >>> conclusions.
> >>
> >> I don't think I've made any specific conclusion (or any predictions).
> > 
> > So your reference to "enacting a ban" is not a conclusion?  Then why
> > are you condemning something about which you still didn't reach any
> > specific conclusions?
> 
> I haven't made any predictions or conclusions as to whether a ban is 
> forthcoming.

That's not how the above reads.



^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: Instead of pcase
  2023-11-19 17:59                 ` Dmitry Gutov
  2023-11-19 19:31                   ` Eric Abrahamsen
@ 2023-11-19 21:15                   ` Barry Fishman
  2023-11-20  1:15                     ` Dmitry Gutov
  2023-11-20 15:32                     ` Michael Heerdegen
  1 sibling, 2 replies; 342+ messages in thread
From: Barry Fishman @ 2023-11-19 21:15 UTC (permalink / raw)
  To: emacs-devel


On 2023-11-19 19:59:42 +02, Dmitry Gutov wrote:
> On 19/11/2023 18:02, Barry Fishman wrote:
>> On 2023-11-19 13:23:17 +01, Michael Heerdegen wrote:
>>> So, the advantage would be more of a psychological kind: you have normal
>>> Lisp function calls, but structurally you have the same thing, and you
>>> have to remember exactly the same set of details.  The complexity comes
>>> from the task, not from the implementation.
>> I submit that the opposite is true,  the complexity is in its
>> implementation, not the task.
>> In languages like Haskell this is expressed in a very simple way, so
>> the
>> task is not in itself hard to understand.
>
> Haskell is notable for using the same (or similar) syntax for
> destructuring as it uses for constructing expressions.
>
> pcase actually follows that practice with backquotes and commas.

Really?  I thought back-quoting was used (as an alternative way) to
construct nested lists, to express more simply the piecing together and
concatenating nested list pieces, particularly in macroes, and its
expansion at compile time is fairly obvious.

I guess what pcase is trying to do is the similar, but it is expressing
something that, to me, seem far more complex to use.

Its also mixing "destructuring" and "guard"s, all in one "super" domain
specific language.

Like loop, it can be powerful, but intimidating to people that don't use
it a lot.  But its usefulness to those that know it, encourages its
use in the code base.

But exiting Lisp destructuring via destructuring-bind and lambda
arguments, don't use backquoting.

One thing I did change was to reverse the defmethod style of (variable
type) to (type variable) to try to simplify recursion in the typeproto
syntax.

> And in both matching and destructuring are done in the same expression
> (the presence of the latter is determined by whether a pattern
> contains variable bindindgs).
>
>> If x is a list with its first element a string "foo" and the second an
>> integer, remove it from x and add the second element to total:
>>    (proto-case x
>>      ((list* (string name) (integer count) (t rest))
>>       (string-equal name "foo")
>>       (set! total (+ total count))
>>       (set! x rest)))
>> This is just one of many other ways one could setup a matching
>> expression in elisp, the best is a balance between implementation
>> efficiency and readability.
>
> And this divorces matching from destructuring. I suggest you try
> rewriting one of the more complex pcase usages into this syntax and
> see what people think of the result.

You want me to guess what you have in mind?  I have no idea.

I'll take the example pcase code from the Emacs manual:

(pcase (get-return-code x)
  ;; string
  ((and (pred stringp) msg) 
        (message "%s" msg))
  ;; symbol
  ('success       (message "Done!"))
  ('would-block   (message "Sorry, can't do it now"))
  ('read-only     (message "The shmliblick is read-only"))
  ('access-denied (message "You do not have the needed rights"))
  ;; default
  (code           (message "Unknown return code %S" code)))

This is a simple use case, so its hard to use to draw any conclusions.

This is mostly value handling for a known type, which is to me a
different problem than destructuring, and be handled better by a
generalized value case structure.  But still:

(let ((msglist
        '((success       . "Done!")
          (would-block   . "Sorry, can't do it now")
          (read-only     . "The shmliblick is read-only")
          (access-denied . "You do not have the needed rights"))))
  (proto-case (get-return-code x)
    ((string msg) t (message "%s" msg))
    ((symbol sym) t (let ((pair (assq sym msglist)))
                      (if pair
                        (message (cdr pair))
                        (message "Unknown return symbol %S" sym))))
    ((t code)     t (message "Unknown return type %S" code))))

In this situation pcase situation is a slightly better, to my
sensibility's. [Now that pcase is written]

One could also define a value oriented traditional style case:

 (vcase (x typecmp default)
     ((value expression ...) ...))

Which tests x using (funcall typecmp x value), and returns default
if there is no match.

And avoid the proto-case all together:

(let ((code (get-return-code)))
  (cond
   ((stringp code) (message "%s" msg))
   ((symbolp code)
    (or (vcase (sym eq nil)
          ('success       (message "Done!"))
          ('would-block   (message "Sorry, can't do it now"))
          ('read-only     (message "The shmliblick is read-only"))
          ('access-denied (message "You do not have the needed rights")))
        (message "Unknown return code %S" sym)))
   (t 
     (message "Unknown return type %S" code))))

-- 
Barry Fishman




^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: combining cond and let, to replace pcase.
  2023-11-19 11:20     ` Michael Heerdegen
                         ` (2 preceding siblings ...)
  2023-11-19 18:10       ` Tomas Hlavaty
@ 2023-11-19 21:36       ` Alan Mackenzie
  2023-11-21 16:14         ` Michael Heerdegen
  3 siblings, 1 reply; 342+ messages in thread
From: Alan Mackenzie @ 2023-11-19 21:36 UTC (permalink / raw)
  To: Michael Heerdegen; +Cc: Richard Stallman, Spencer Baugh, emacs-devel

Hello, Michael.

On Sun, Nov 19, 2023 at 12:20:20 +0100, Michael Heerdegen wrote:
> Richard Stallman <rms@gnu.org> writes:

> > Some of them could do destructuring as well as matching.

> > I hoipe that using a few constructs to divide up the job will avoid
> > the kludginess of pcase's bells-and-whistles-for-everything approach,
> > resulting in something equally convenient but made of simple
> > components.

> I really don't know how you come to such a conclusion.

> The original docstring of `pcase' was half of a screen page and it was
> _complete_.  Syntax and semantics are simple, nearly trivial, and
> consistent.  It took one minute for me to learn everything.  Then the
> doc has been extended to the current form adding more prose, in my eyes,
> it added not a single bit of information.

The original doc string of pcase was not a high quality one.  See the
thread in emacs-devel Subject: The poor state of documentation of pcase
like things, started by me on 2015-12-16.

Some of its deficiencies, listed in that post, were (i) Use of obscure
terms like U-pattern and Q-pattern which it failed to define; (ii) the
semantics of these structures was not elucidated; (iii) there was no
rigorous definition of what ` and , mean in pcase structures; (iv) there
was no specification of when a pcase pattern matched something; (v)
there was no specification of when and how variables got bound.

The doc string didn't say in accessible language what pcase does.

But I'm repeating myself.  It's all in that 8 year old post.

I may be mis-remembering, but I think it was you, Michael, who put in
the work to fix these defects in pcase's doc string.  The result was far
better than the original.

> If some people have a problem understanding the abstract approach, this
> is something different.  But a "kludginess of pcase's
> bells-and-whistles-for-everything approach" does not exist.  So please
> understand that your approach will make the situation worse for others.

> To me this discussion looks like some people aren't willing to accept
> multiplication like 10*5 because it "looks strange" and "one would rather
> write "5+5+5+5+5+5+5+5+5+5" because this would be much simpler and we
> don't need this strange "*" at all.

> Is this unfair?  I don't know.  But are there any _objective_ reasons
> why the design of `pcase' would not be optimal?  To me this all looks
> more like being based on vague feelings because the approach is a bit
> different from what people are used to.  But the approach is extremely
> simple.  I think that replacing it with multiple other tools would
> complicate the matter.

pcase complicated the meaning of ` and ,.  Before pcase these had
definite meanings.  Afterwards, they became highly context dependent.
The usual evasive reply from pcase proponents here is that ` has always
been an abbreviation for backslash and that didn't change.  A lot
changed, here.  An alternative here would have been to invent new reader
macros instead of complicating and ambiguating ` and ,.

[ .... ]

> Michael.

-- 
Alan Mackenzie (Nuremberg, Germany).



^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: Instead of pcase
  2023-11-19 21:15                   ` Barry Fishman
@ 2023-11-20  1:15                     ` Dmitry Gutov
  2023-11-20 15:32                     ` Michael Heerdegen
  1 sibling, 0 replies; 342+ messages in thread
From: Dmitry Gutov @ 2023-11-20  1:15 UTC (permalink / raw)
  To: Barry Fishman, emacs-devel

On 19/11/2023 23:15, Barry Fishman wrote:

>> Haskell is notable for using the same (or similar) syntax for
>> destructuring as it uses for constructing expressions.
>>
>> pcase actually follows that practice with backquotes and commas.
> 
> Really?  I thought back-quoting was used (as an alternative way) to
> construct nested lists, to express more simply the piecing together and
> concatenating nested list pieces, particularly in macroes, and its
> expansion at compile time is fairly obvious.
> 
> I guess what pcase is trying to do is the similar,

The reverse, to be more exact.

> but it is expressing
> something that, to me, seem far more complex to use.

I don't blame you, FWIW. But I've yet to see a "simpler" solution which 
would provide comparable functionality.

> Its also mixing "destructuring" and "guard"s, all in one "super" domain
> specific language.
> 
> Like loop, it can be powerful, but intimidating to people that don't use
> it a lot.  But its usefulness to those that know it, encourages its
> use in the code base.
> 
> But exiting Lisp destructuring via destructuring-bind and lambda
> arguments, don't use backquoting.
They also don't provide any pattern matching of case-like functionality.

When you don't need a way to distinguish literals from variables, 
(un)quoting is indeed not needed.

> One thing I did change was to reverse the defmethod style of (variable
> type) to (type variable) to try to simplify recursion in the typeproto
> syntax.
> 
>> And in both matching and destructuring are done in the same expression
>> (the presence of the latter is determined by whether a pattern
>> contains variable bindindgs).
>>
>>> If x is a list with its first element a string "foo" and the second an
>>> integer, remove it from x and add the second element to total:
>>>     (proto-case x
>>>       ((list* (string name) (integer count) (t rest))
>>>        (string-equal name "foo")
>>>        (set! total (+ total count))
>>>        (set! x rest)))
>>> This is just one of many other ways one could setup a matching
>>> expression in elisp, the best is a balance between implementation
>>> efficiency and readability.
>>
>> And this divorces matching from destructuring. I suggest you try
>> rewriting one of the more complex pcase usages into this syntax and
>> see what people think of the result.
> 
> You want me to guess what you have in mind?  I have no idea.

I meant that you could try to take an example of a complex usage of 
pcase (one that seemed complex to you), some big expression or at least 
one that exhibits most of pcase's functionalities, and try rewriting it 
using an alternative syntax. And then judge for yourself, and then maybe 
poll others, which solution looks more readable and easier to understand.

> I'll take the example pcase code from the Emacs manual:
> 
> (pcase (get-return-code x)
>    ;; string
>    ((and (pred stringp) msg)
>          (message "%s" msg))
>    ;; symbol
>    ('success       (message "Done!"))
>    ('would-block   (message "Sorry, can't do it now"))
>    ('read-only     (message "The shmliblick is read-only"))
>    ('access-denied (message "You do not have the needed rights"))
>    ;; default
>    (code           (message "Unknown return code %S" code)))
> 
> This is a simple use case, so its hard to use to draw any conclusions.
> 
> This is mostly value handling for a known type, which is to me a
> different problem than destructuring, and be handled better by a
> generalized value case structure.  But still:
> 
> (let ((msglist
>          '((success       . "Done!")
>            (would-block   . "Sorry, can't do it now")
>            (read-only     . "The shmliblick is read-only")
>            (access-denied . "You do not have the needed rights"))))
>    (proto-case (get-return-code x)
>      ((string msg) t (message "%s" msg))
>      ((symbol sym) t (let ((pair (assq sym msglist)))
>                        (if pair
>                          (message (cdr pair))
>                          (message "Unknown return symbol %S" sym))))
>      ((t code)     t (message "Unknown return type %S" code))))
> 
> In this situation pcase situation is a slightly better, to my
> sensibility's. [Now that pcase is written]

Indeed, I don't see an improvement either. I'd say it looks worse 
because of the slight increase in verbosity, but they're close enough.

That's why I suggested picking some relatively complex example to 
rewrite: more potential to show a difference.



^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: Instead of pcase
  2023-11-16 15:06 ` Michael Heerdegen
  2023-11-16 17:31   ` T.V Raman
@ 2023-11-20  3:06   ` Richard Stallman
  2023-11-20 14:35     ` Michael Heerdegen
  1 sibling, 1 reply; 342+ messages in thread
From: Richard Stallman @ 2023-11-20  3:06 UTC (permalink / raw)
  To: Michael Heerdegen; +Cc: emacs-devel

[[[ To any NSA and FBI agents reading my email: please consider    ]]]
[[[ whether defending the US Constitution against all enemies,     ]]]
[[[ foreign or domestic, requires you to follow Snowden's example. ]]]

  > > But don't argue that this cost does not exist, simply because it
  > > doesn't feel like a burden to you.

  > Hmm, I must say that cost was small for me.  There is also a cost of
  > reading a more complicated rewrite using less suited language
  > constructs.

It would not be more complicated in substance.  It would only be less
terse in the way it is written.

  > I wonder how that would look like and if it would really be simpler.  Or
  > if it would be structurally more or less equivalent and only avoid the
  > concise syntax.

I hope it will be similar but avoid the tersd syntax.
I have not finished design it, but I made some progress today.

Would you like to help design matching functions to do the same jobs
that pcase does?  I would like to make it possible to combine
various matching and destructuring functions using `and' and `or'
(plus any other Lisp functions you like).



-- 
Dr Richard Stallman (https://stallman.org)
Chief GNUisance of the GNU Project (https://gnu.org)
Founder, Free Software Foundation (https://fsf.org)
Internet Hall-of-Famer (https://internethalloffame.org)





^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: Instead of pcase
  2023-11-20  3:06   ` Richard Stallman
@ 2023-11-20 14:35     ` Michael Heerdegen
  2023-11-23  2:57       ` Richard Stallman
  0 siblings, 1 reply; 342+ messages in thread
From: Michael Heerdegen @ 2023-11-20 14:35 UTC (permalink / raw)
  To: emacs-devel

Richard Stallman <rms@gnu.org> writes:

> Would you like to help design matching functions to do the same jobs
> that pcase does?

With pleasure, I'll try to do my best.

> I would like to make it possible to combine various matching and
> destructuring functions using `and' and `or' (plus any other Lisp
> functions you like).

Would this still be based on pcase or be something completely new?

Michael.




^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: Instead of pcase
  2023-11-19 15:09           ` Eli Zaretskii
@ 2023-11-20 14:52             ` Michael Heerdegen
  0 siblings, 0 replies; 342+ messages in thread
From: Michael Heerdegen @ 2023-11-20 14:52 UTC (permalink / raw)
  To: emacs-devel

Eli Zaretskii <eliz@gnu.org> writes:

> > I'm curious how an alternative could look like, actually.
>
> I don't know.  So I withdraw my judgment until such an alternative is
> presented.  I suggest that everyone do the same.
>
> > It would have to implement the same set of features, so it would be
> > quite as complex as `pcase'.
>
> Complexity doesn't necessarily mean cryptic syntax.  Cf regexp strings
> vs Rx.

If you meant to imply that pcase has a unnecessarily "cryptic syntax",
this is a judgment.  If you wish that the syntax should be more like
human language, or more verbose, or less like a new mini-language, this
is an opinion.  Which is ok.  But not as neutral as your first sentence
suggests.  Still fine by me.

But when this is a opinion, and other people differ, we also should
speak about the disadvantages of a different approach.  For example, if
we replace the backquote syntax with something that looks more like
function calls, it would be less obvious at which depth and which
position a subpattern is matched.  Since pcase has been introduced to
make specification of complex, nested patterns easier and more compact
to read, we will lose this advantage.  The syntax might be easier to
learn, but code will be harder to maintain and tweak.  At least for me.

But I repeat myself.  I guess it's clear to you what I want to say, so
you don't need to waste your time to reply, unless you disagree or like
to do so nonetheless of course.

Michael.




^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: Instead of pcase
  2023-11-19 14:29       ` Po Lu
@ 2023-11-20 15:20         ` Michael Heerdegen
  2023-11-20 15:29         ` Dmitry Gutov
  1 sibling, 0 replies; 342+ messages in thread
From: Michael Heerdegen @ 2023-11-20 15:20 UTC (permalink / raw)
  To: emacs-devel

Po Lu <luangruo@yahoo.com> writes:

> This is a representative microcosm of the wider Emacs userbase, I
> think: for most are not hobbyists, or even employed programmers for
> whom programming is also an avocation, but men working for salaries,
> with bills to pay and families to... you can complete the rest of this
> trite description.

It is not representative for the people working on Emacs.  Even less
representative for the people working on the more complicated parts of
Emacs like the implementation of the completion mechanism.

>  And it is they whom I canvassed.
>
> I sent a poll to 34 individuals, all in some capacity involved in the
> maintenance of Emacs Lisp.  Some of the questions asked were:
> [...]

Interesting results, thanks.

This proves that the learning curve for `pcase' is steep.  As is for
Emacs.  This is not such a surprise.  Your poll doesn't measure whether
it pays off or not.

> > Interesting would be to hear concrete arguments, but we heard nearly
> > none.  "I'm angry" is not an argument.
>
> No one in this thread has been presenting indignation as an argument.

Not like "this is my argument: ...", no.  I meant I heard a lot of
emotion instead of arguments.


Michael.




^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: Instead of pcase
  2023-11-19 14:29       ` Po Lu
  2023-11-20 15:20         ` Michael Heerdegen
@ 2023-11-20 15:29         ` Dmitry Gutov
  2023-11-20 23:43           ` Po Lu
  2023-11-20 23:45           ` Jose E. Marchesi
  1 sibling, 2 replies; 342+ messages in thread
From: Dmitry Gutov @ 2023-11-20 15:29 UTC (permalink / raw)
  To: Po Lu, Michael Heerdegen; +Cc: Jim Porter, rms, emacs-devel

On 19/11/2023 16:29, Po Lu wrote:
> My organization largely comprises C programmers who use Emacs for
> programming, as a means to an end rather than an end in itself.  Our two
> sites centrally provision their own Emacs configurations to all users,
> which incorporates a large corpus of code for editing and analyzing C
> programs in accord with local practice.  Naturally, the existence of
> this corpus demands that programmers be charged with its upkeep, and as
> no position is set aside for such work, this responsibility devolves on
> individuals almost at random.  This is a representative microcosm of the
> wider Emacs userbase, I think: for most are not hobbyists, or even
> employed programmers for whom programming is also an avocation, but men
> working for salaries, with bills to pay and families to... you can
> complete the rest of this trite description.  And it is they whom I
> canvassed.

Polling professional C developers on whether they are comfortable with 
advanced syntax inspired by high-level languages like ML or Haskell is 
pretty much a self-fulfilling prophecy.

Ask a company of OCaml developers (we have at least one representative 
of such among active contributors), or even a corpus of experienced 
JavaScript developers, the results will be different.

Anyway, the results confirm what we've been aware of for some time: that 
the documentation for pcase needs work. Jim Porter's list of steps 
should help a lot.



^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: Instead of pcase
  2023-11-19 21:15                   ` Barry Fishman
  2023-11-20  1:15                     ` Dmitry Gutov
@ 2023-11-20 15:32                     ` Michael Heerdegen
  2023-11-23  2:57                       ` Richard Stallman
  1 sibling, 1 reply; 342+ messages in thread
From: Michael Heerdegen @ 2023-11-20 15:32 UTC (permalink / raw)
  To: emacs-devel

Barry Fishman <barry@ecubist.org> writes:

> Its also mixing "destructuring" and "guard"s, all in one "super"
> domain specific language.

This is the requirement: in some situations a code path should only be
chosen when a certain structure is present and certain requirements for
certain parts of the structure are fulfilled.  When you separate these
two things artificially you will make the thing more complicated, you
need to introduce extra bindings (for the tests) that the BODY doesn't
use, resulting in poorly readable code.

> I'll take the example pcase code from the Emacs manual:
> [...]
> and be handled better by a generalized value case structure.

These examples have been added to ease learning.  They are not typical
use cases of course.

Michael.




^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: combining cond and let, to replace pcase.
  2023-11-19 14:45               ` Eli Zaretskii
@ 2023-11-20 15:35                 ` Michael Heerdegen
  2023-11-20 16:37                   ` Eli Zaretskii
  0 siblings, 1 reply; 342+ messages in thread
From: Michael Heerdegen @ 2023-11-20 15:35 UTC (permalink / raw)
  To: emacs-devel

Eli Zaretskii <eliz@gnu.org> writes:

> > And why is it always suggested that people not liking pcase are the
> > norm and those understanding it well are the deviation from the
> > norm?
>
> Who and where suggested that?

That's how it feels on this side of the discussion.  Do I really need to
prove this?  I could do that, but it would be a waste of time I guess,
and I partially did that in other places of this thread.

> [I snipped all the rest of your message because it just expresses your
> opinions, and we already agreed that opinions differ on this.]

Sure.


Michael.




^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: combining cond and let, to replace pcase.
  2023-11-20 15:35                 ` Michael Heerdegen
@ 2023-11-20 16:37                   ` Eli Zaretskii
  2023-11-21  8:33                     ` Michael Heerdegen
  0 siblings, 1 reply; 342+ messages in thread
From: Eli Zaretskii @ 2023-11-20 16:37 UTC (permalink / raw)
  To: Michael Heerdegen; +Cc: emacs-devel

> From: Michael Heerdegen <michael_heerdegen@web.de>
> Date: Mon, 20 Nov 2023 16:35:33 +0100
> 
> Eli Zaretskii <eliz@gnu.org> writes:
> 
> > > And why is it always suggested that people not liking pcase are the
> > > norm and those understanding it well are the deviation from the
> > > norm?
> >
> > Who and where suggested that?
> 
> That's how it feels on this side of the discussion.  Do I really need to
> prove this?

You don't need to prove how you feel, but I respectfully request that
before you make such feelings public, you double-check your feelings
with the actual postings.  It is quite possible that your initial
interpretation of what you've read was not the only one.  This is
supposed to be a rational discussion, not one based on feelings.

As a matter of fact, I'm not aware of any such suggestions in this and
other similar discussions, and if someone actually said that (which I
doubt), they don't speak for the project as a whole.  So let's drop
this part of the discussion, since it is nowhere near being
constructive.



^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: Instead of pcase
  2023-11-20 15:29         ` Dmitry Gutov
@ 2023-11-20 23:43           ` Po Lu
  2023-11-21  1:09             ` Dmitry Gutov
  2023-11-20 23:45           ` Jose E. Marchesi
  1 sibling, 1 reply; 342+ messages in thread
From: Po Lu @ 2023-11-20 23:43 UTC (permalink / raw)
  To: Dmitry Gutov; +Cc: Michael Heerdegen, Jim Porter, rms, emacs-devel

Dmitry Gutov <dmitry@gutov.dev> writes:

> Polling professional C developers on whether they are comfortable with
> advanced syntax inspired by high-level languages like ML or Haskell is
> pretty much a self-fulfilling prophecy.
>
> Ask a company of OCaml developers (we have at least one representative
> of such among active contributors), or even a corpus of experienced
> JavaScript developers, the results will be different.

How many O'Caml developers are there?  It's not plausible that they
number greater than C developers (for that matter I don't think there's
any O'Caml software on my computer).

> Anyway, the results confirm what we've been aware of for some time:
> that the documentation for pcase needs work. Jim Porter's list of
> steps should help a lot.

They substantiate in equal measure that pcase itself is ungainly to some
Emacs users--some people here are loath to accept that, but the facts
are what they are.  Whether other Emacs users relish it is beside the
point.



^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: Instead of pcase
  2023-11-20 15:29         ` Dmitry Gutov
  2023-11-20 23:43           ` Po Lu
@ 2023-11-20 23:45           ` Jose E. Marchesi
  2023-11-20 23:54             ` Emanuel Berg
  2023-11-21  2:01             ` Dmitry Gutov
  1 sibling, 2 replies; 342+ messages in thread
From: Jose E. Marchesi @ 2023-11-20 23:45 UTC (permalink / raw)
  To: Dmitry Gutov; +Cc: Po Lu, Michael Heerdegen, Jim Porter, rms, emacs-devel


> On 19/11/2023 16:29, Po Lu wrote:
>> My organization largely comprises C programmers who use Emacs for
>> programming, as a means to an end rather than an end in itself.  Our two
>> sites centrally provision their own Emacs configurations to all users,
>> which incorporates a large corpus of code for editing and analyzing C
>> programs in accord with local practice.  Naturally, the existence of
>> this corpus demands that programmers be charged with its upkeep, and as
>> no position is set aside for such work, this responsibility devolves on
>> individuals almost at random.  This is a representative microcosm of the
>> wider Emacs userbase, I think: for most are not hobbyists, or even
>> employed programmers for whom programming is also an avocation, but men
>> working for salaries, with bills to pay and families to... you can
>> complete the rest of this trite description.  And it is they whom I
>> canvassed.
>
> Polling professional C developers on whether they are comfortable with
> advanced syntax inspired by high-level languages like ML or Haskell is
> pretty much a self-fulfilling prophecy.
>
> Ask a company of OCaml developers (we have at least one representative
> of such among active contributors), or even a corpus of experienced
> JavaScript developers, the results will be different.

Following your own reasoning, wouldn't it be also reasonable to expect
that the vast majority of Lisp developers won't be comfortable with such
an "advanced syntax", considering that Lisp (unlike C) has basically no
syntax?

> Anyway, the results confirm what we've been aware of for some time:
> that the documentation for pcase needs work. Jim Porter's list of
> steps should help a lot.



^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: Instead of pcase
  2023-11-20 23:45           ` Jose E. Marchesi
@ 2023-11-20 23:54             ` Emanuel Berg
  2023-11-21  2:01             ` Dmitry Gutov
  1 sibling, 0 replies; 342+ messages in thread
From: Emanuel Berg @ 2023-11-20 23:54 UTC (permalink / raw)
  To: emacs-devel

Jose E. Marchesi wrote:

>>> My organization largely comprises C programmers who use
>>> Emacs for programming, as a means to an end rather than an
>>> end in itself. Our two sites centrally provision their own
>>> Emacs configurations to all users, which incorporates
>>> a large corpus of code for editing and analyzing
>>> C programs in accord with local practice. Naturally, the
>>> existence of this corpus demands that programmers be
>>> charged with its upkeep, and as no position is set aside
>>> for such work, this responsibility devolves on individuals
>>> almost at random. This is a representative microcosm of
>>> the wider Emacs userbase, I think: for most are not
>>> hobbyists, or even employed programmers for whom
>>> programming is also an avocation, but men working for
>>> salaries, with bills to pay and families to... you can
>>> complete the rest of this trite description. And it is
>>> they whom I canvassed.
>>
>> Polling professional C developers on whether they are
>> comfortable with advanced syntax inspired by high-level
>> languages like ML or Haskell is pretty much
>> a self-fulfilling prophecy.
>>
>> Ask a company of OCaml developers (we have at least one
>> representative of such among active contributors), or even
>> a corpus of experienced JavaScript developers, the results
>> will be different.
>
> Following your own reasoning, wouldn't it be also reasonable
> to expect that the vast majority of Lisp developers won't be
> comfortable with such an "advanced syntax", considering that
> Lisp (unlike C) has basically no syntax?

Maybe we should add some parenthesis to pcase, if that will
make the Lisp programmers more comfortable using it?

-- 
underground experts united
https://dataswamp.org/~incal




^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: Instead of pcase
  2023-11-20 23:43           ` Po Lu
@ 2023-11-21  1:09             ` Dmitry Gutov
  2023-11-21  1:49               ` Po Lu
  0 siblings, 1 reply; 342+ messages in thread
From: Dmitry Gutov @ 2023-11-21  1:09 UTC (permalink / raw)
  To: Po Lu; +Cc: Michael Heerdegen, Jim Porter, rms, emacs-devel

On 21/11/2023 01:43, Po Lu wrote:
> Dmitry Gutov <dmitry@gutov.dev> writes:
> 
>> Polling professional C developers on whether they are comfortable with
>> advanced syntax inspired by high-level languages like ML or Haskell is
>> pretty much a self-fulfilling prophecy.
>>
>> Ask a company of OCaml developers (we have at least one representative
>> of such among active contributors), or even a corpus of experienced
>> JavaScript developers, the results will be different.
> 
> How many O'Caml developers are there?  It's not plausible that they
> number greater than C developers (for that matter I don't think there's
> any O'Caml software on my computer).

OCaml -- maybe not that many. But the sum total of developers writing in 
high-level languages (JavaScript included) is quite high.

Ruby and Python have pattern matching in that style. Rust and Swift do too.

JS might be getting one in a few years: 
https://github.com/tc39/proposal-pattern-matching

Java introduced limited/experimental support this year: 
https://openjdk.org/jeps/432

Even the C++ standard might get it one day: 
https://www.stroustrup.com/pattern-matching-November-2014.pdf (libraries 
already available)



^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: Instead of pcase
  2023-11-21  1:09             ` Dmitry Gutov
@ 2023-11-21  1:49               ` Po Lu
  2023-11-21  1:59                 ` Dmitry Gutov
  0 siblings, 1 reply; 342+ messages in thread
From: Po Lu @ 2023-11-21  1:49 UTC (permalink / raw)
  To: Dmitry Gutov; +Cc: Michael Heerdegen, Jim Porter, rms, emacs-devel

Dmitry Gutov <dmitry@gutov.dev> writes:

> OCaml -- maybe not that many. But the sum total of developers writing
> in high-level languages (JavaScript included) is quite high.
>
> Ruby and Python have pattern matching in that style. Rust and Swift do
> too.
>
> JS might be getting one in a few years:
> https://github.com/tc39/proposal-pattern-matching
>
> Java introduced limited/experimental support this year:
> https://openjdk.org/jeps/432
>
> Even the C++ standard might get it one day:
> https://www.stroustrup.com/pattern-matching-November-2014.pdf
> (libraries already available)

That's all well and good, but one of Richard's requests at the outset of
this thread was:

> It's just the opposite for `pcase' -- its specific purpose is a
> low-level purpose, so it could appear in any part of the code of
> Emacs, The burden of its complexity can fall on any or all of us.

> Those of you who are fans of `pcase' may not recognize the cost it
> imposes on the Emacs Lisp language.  You paid that cost already,
> perhaps a few years ago, and perhaps you enjoy each new language
> construct you learn.  Perhaps, for you, the more complexity of
> features to be learned, the better.

> But don't argue that this cost does not exist, simply because it
> doesn't feel like a burden to you.

And thus far this thread has been awash with denials of that burden, one
which unequivocally exists.  This I and others have demonstrated time
and again.

pcase is _not_ fine as-is, however many other languages might provide
analogous constructs.  One man's meat is another man's poison; and it is
up to us to place before either neither his meat nor his poison.



^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: Instead of pcase
  2023-11-21  1:49               ` Po Lu
@ 2023-11-21  1:59                 ` Dmitry Gutov
  2023-11-21  4:04                   ` Po Lu
  0 siblings, 1 reply; 342+ messages in thread
From: Dmitry Gutov @ 2023-11-21  1:59 UTC (permalink / raw)
  To: Po Lu; +Cc: Michael Heerdegen, Jim Porter, rms, emacs-devel

On 21/11/2023 03:49, Po Lu wrote:
>> It's just the opposite for `pcase' -- its specific purpose is a
>> low-level purpose, so it could appear in any part of the code of
>> Emacs, The burden of its complexity can fall on any or all of us.

That's not accurate: its purpose is a high-level one. Even though it can 
be used as a replacement for 'cond' in simple case too.

> But don't argue that this cost does not exist, simply because it
> doesn't feel like a burden to you.

Did I?



^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: Instead of pcase
  2023-11-20 23:45           ` Jose E. Marchesi
  2023-11-20 23:54             ` Emanuel Berg
@ 2023-11-21  2:01             ` Dmitry Gutov
  2023-11-22  2:59               ` Richard Stallman
  1 sibling, 1 reply; 342+ messages in thread
From: Dmitry Gutov @ 2023-11-21  2:01 UTC (permalink / raw)
  To: Jose E. Marchesi; +Cc: Po Lu, Michael Heerdegen, Jim Porter, rms, emacs-devel

On 21/11/2023 01:45, Jose E. Marchesi wrote:
> Following your own reasoning, wouldn't it be also reasonable to expect
> that the vast majority of Lisp developers won't be comfortable with such
> an "advanced syntax", considering that Lisp (unlike C) has basically no
> syntax?

In Lisps, most of the complexity simply moved to standard library 
(and/or other libraries as well). Look at Common Lisp (cl-lib derived 
from it is bemoaned in a nearby thread) or Clojure.



^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: Instead of pcase
  2023-11-19 13:49             ` Dmitry Gutov
@ 2023-11-21  2:42               ` Richard Stallman
  2023-11-21  5:14                 ` Jim Porter
                                   ` (4 more replies)
  0 siblings, 5 replies; 342+ messages in thread
From: Richard Stallman @ 2023-11-21  2:42 UTC (permalink / raw)
  To: Dmitry Gutov; +Cc: philipk, emacs-devel

[[[ To any NSA and FBI agents reading my email: please consider    ]]]
[[[ whether defending the US Constitution against all enemies,     ]]]
[[[ foreign or domestic, requires you to follow Snowden's example. ]]]

  > > They contain code that looks like Lisp but does not have the same
  > > semantic rules as Lisp.

  > Yes: it's a domain-specific language.

THat is why pcase adds to the total complexity of Emacs Lisp: because
it incorporates a domain-specific language.  (I called it a "little
lajguage".)

  > To interpret those backquotes and commas, one can imagine that the they 
  > do the inverse of the usual.

I uderstand that when you say it, but when I saw the line

>          > (`(,hookfun . (,start ,end ,collection . ,plist))

I was not sure which part of the line that rule applies to.

In particular, what is the reason for the period and inner
parenthsses?  Why doesn't the code say this?

>          > (`(,hookfun ,start ,end ,collection . ,plist)

Would that be equiva;ent?

I could not assume the inner parenthsses were unnecessary.  Maybe
there was a conventiob by which they change the meaning.
I did not know.



-- 
Dr Richard Stallman (https://stallman.org)
Chief GNUisance of the GNU Project (https://gnu.org)
Founder, Free Software Foundation (https://fsf.org)
Internet Hall-of-Famer (https://internethalloffame.org)





^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: Instead of pcase
  2023-11-19 14:58             ` Dmitry Gutov
  2023-11-19 15:14               ` Eli Zaretskii
@ 2023-11-21  2:43               ` Richard Stallman
  1 sibling, 0 replies; 342+ messages in thread
From: Richard Stallman @ 2023-11-21  2:43 UTC (permalink / raw)
  To: Dmitry Gutov; +Cc: emacs-devel

[[[ To any NSA and FBI agents reading my email: please consider    ]]]
[[[ whether defending the US Constitution against all enemies,     ]]]
[[[ foreign or domestic, requires you to follow Snowden's example. ]]]

  > No one is arguing about whether people are allowed to post opinions.

Some are doing something somewhat like that.

I have criticized CL, and pcase, for bloating the complexity of Emacs
Lisp as one needs to know it to work on the current code base.  Others
disagree and have defended those features.

I think that the disagreement on these questions is based on
differing ideas about about what makes a feature good or bad.

However, there are people who have switched to an ad-hominem campaign.
They are not attacking my views about CL and pcase; rather, they are
attacking me personally.


-- 
Dr Richard Stallman (https://stallman.org)
Chief GNUisance of the GNU Project (https://gnu.org)
Founder, Free Software Foundation (https://fsf.org)
Internet Hall-of-Famer (https://internethalloffame.org)





^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: Instead of pcase
  2023-11-21  1:59                 ` Dmitry Gutov
@ 2023-11-21  4:04                   ` Po Lu
  2023-11-21 11:27                     ` Dmitry Gutov
  0 siblings, 1 reply; 342+ messages in thread
From: Po Lu @ 2023-11-21  4:04 UTC (permalink / raw)
  To: Dmitry Gutov; +Cc: Michael Heerdegen, Jim Porter, rms, emacs-devel

Dmitry Gutov <dmitry@gutov.dev> writes:

> That's not accurate: its purpose is a high-level one. Even though it
> can be used as a replacement for 'cond' in simple case too.

Destructuring variable binding is not a high-level use case.  As Richard
mentioned, such a definition is subject to the amount of Lisp there is
possibly a role for it in.  And needless to say, this amount is
significant in the case of pcase, and is small in that of quail.

>> But don't argue that this cost does not exist, simply because it
>> doesn't feel like a burden to you.
>
> Did I?

That's how it came across to me.  "The burden is immaterial since many
categories of programmers do not perceive it as such" is not much
different from "the burden does not exist," when the inferences drawn
from both are identical, to wit: that pcase is fine as it is.



^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: Instead of pcase
  2023-11-21  2:42               ` Richard Stallman
@ 2023-11-21  5:14                 ` Jim Porter
  2023-11-21  5:34                 ` Yuri Khan
                                   ` (3 subsequent siblings)
  4 siblings, 0 replies; 342+ messages in thread
From: Jim Porter @ 2023-11-21  5:14 UTC (permalink / raw)
  To: rms, Dmitry Gutov; +Cc: philipk, emacs-devel

On 11/20/2023 6:42 PM, Richard Stallman wrote:
> I uderstand that when you say it, but when I saw the line
> 
>>           > (`(,hookfun . (,start ,end ,collection . ,plist))
> 
> I was not sure which part of the line that rule applies to.
> 
> In particular, what is the reason for the period and inner
> parenthsses?  Why doesn't the code say this?
> 
>>           > (`(,hookfun ,start ,end ,collection . ,plist)
> 
> Would that be equiva;ent?

Yes, These are equivalent (unless I'm severely mistaken):

----------------------------------------

(pcase '(func 0 10 coll plist1 plist2)
   (`(,hookfun . (,start ,end ,collection . ,plist))
    (message "hookfun = %s start = %s end = %s collection = %s plist = %s"
             hookfun start end collection plist)))

  => "hookfun = func start = 0 end = 10 collection = coll plist = 
(plist1 plist2)"


(pcase '(func 0 10 coll plist1 plist2)
   (`(,hookfun ,start ,end ,collection . ,plist)
    (message "hookfun = %s start = %s end = %s collection = %s plist = %s"
             hookfun start end collection plist)))

  => "hookfun = func start = 0 end = 10 collection = coll plist = 
(plist1 plist2)"

----------------------------------------

> I could not assume the inner parenthsses were unnecessary.  Maybe
> there was a conventiob by which they change the meaning.
> I did not know.

I think this might be a case where the 'pcase' code was written in a 
more-cryptic-than-necessary manner, which adds extra confusion. This 
could be a good example to include in some documentation though: it can 
show how one's intuition about "ordinary" backquoted forms can apply 
directly to reading 'pcase'.



^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: Instead of pcase
  2023-11-21  2:42               ` Richard Stallman
  2023-11-21  5:14                 ` Jim Porter
@ 2023-11-21  5:34                 ` Yuri Khan
  2023-11-21 11:11                 ` Dmitry Gutov
                                   ` (2 subsequent siblings)
  4 siblings, 0 replies; 342+ messages in thread
From: Yuri Khan @ 2023-11-21  5:34 UTC (permalink / raw)
  To: rms; +Cc: Dmitry Gutov, philipk, emacs-devel

On Tue, 21 Nov 2023 at 09:42, Richard Stallman <rms@gnu.org> wrote:
>   > To interpret those backquotes and commas, one can imagine that the they
>   > do the inverse of the usual.
>
> I uderstand that when you say it, but when I saw the line
>
> >          > (`(,hookfun . (,start ,end ,collection . ,plist))
>
> I was not sure which part of the line that rule applies to.
>
> In particular, what is the reason for the period and inner
> parenthsses?  Why doesn't the code say this?
>
> >          > (`(,hookfun ,start ,end ,collection . ,plist)
>
> Would that be equiva;ent?

I am looking at this part of code for the first time so let’s see what
I can make of it.

The code in the revision I’m looking at looks like this:

    (defun completion-at-point ()
      "…"
      (interactive)
      (let ((res (run-hook-wrapped 'completion-at-point-functions
                                   #'completion--capf-wrapper 'all)))
        (pcase res
          (`(,_ . ,(and (pred functionp) f)) (funcall f))
          (`(,hookfun . (,start ,end ,collection . ,plist))
           …)
          ;; Maybe completion already happened and the function returned t.
          (_
           …))))

First, this runs a hook and binds its returned value to the local name ‘res’.

Then it matches that value to one of three patterns, the last of which
is a match-all. The first two look like they match ‘res’ to a cons
cell. I go to look a the documentation of
‘completion-at-point-functions’:

    should return either nil, meaning it is not applicable at point,
    or a function of no arguments to perform completion (discouraged),
    or a list of the form (START END COLLECTION . PROPS), where:

Aha! The two latter formats are the same as the inner matchers in the
first two pcase alternatives. I look at ‘completion--capf-wrapper’ to
see if it supplies the ‘car’ part.

    (defun completion--capf-wrapper (fun which)
      (if …
          (let ((res (funcall fun)))
             …
             (if res (cons fun res)))))

It seems it does! So the pcase matchers in ‘completion-at-point’ are
written that way because the wrapper returns a cons cell with the
function in car and its result in cdr, and one of the possible formats
of the result is a sub-list.

I’m pretty sure collapsing that `(,hookfun . (,start …)) to `(,hookfun
,start …) would be an equivalent transformation, but I also feel it
would mash together the expectations from the wrapper and the
completion-at-point function thus increasing cognitive load for the
reader.


I further notice that, curiously, the inside of
‘completion--capf-wrapper’ analyses the result of (funcall fun) with a
cond, consp, listp, functionp, and nthcdr 3 to check some conditions,
then extracts its car, nth 2, and nthcdr 3 to pass them to a nested
‘try-completion’ call, and it’s not trivial for me to follow as I have
to keep in mind the general structure of the list. If I were trying to
grok that function, I would, for personal reference, try to rewrite it
to pcase, binding the parts of the list to descriptive names.



^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: combining cond and let, to replace pcase.
  2023-11-20 16:37                   ` Eli Zaretskii
@ 2023-11-21  8:33                     ` Michael Heerdegen
  2023-11-21  8:39                       ` Michael Heerdegen
  0 siblings, 1 reply; 342+ messages in thread
From: Michael Heerdegen @ 2023-11-21  8:33 UTC (permalink / raw)
  To: emacs-devel

Eli Zaretskii <eliz@gnu.org> writes:

> You don't need to prove how you feel, but I respectfully request that
> before you make such feelings public, you double-check your feelings
> with the actual postings.

I assure you they are there for a reason.

> It is quite possible that your initial interpretation of what you've
> read was not the only one.  This is supposed to be a rational
> discussion, not one based on feelings.

As far as I know, there is no rational discussion between humans, this
is naïve wishful thinking.  This discussion has been _highly_ emotional
from the beginning, and not because of me.  It had been based on
feelings to a large extent.  Just not explicitly.

As far as I know, hiding feelings behind arguments leads to more
subliminal aggression, leads to women staying out of the discussion (has
anyone ever wondered why nearly no women are present here?) and lets
discussions escalate more quickly, as we already have seen in this
thread.

Please don't misunderstood: of course should any discussion revolve
around arguments and ideas.  But we are humans and also have to deal
with that aspect.  So far, we haven't dealt with it in an optimal way,
in my opinion.


Michael.




^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: combining cond and let, to replace pcase.
  2023-11-21  8:33                     ` Michael Heerdegen
@ 2023-11-21  8:39                       ` Michael Heerdegen
  0 siblings, 0 replies; 342+ messages in thread
From: Michael Heerdegen @ 2023-11-21  8:39 UTC (permalink / raw)
  To: emacs-devel

Michael Heerdegen <michael_heerdegen@web.de> writes:

> But we are humans and also have to deal with that aspect.  So far, we
> haven't dealt with it in an optimal way, in my opinion.

I didn't intent to say that you would not be doing a good job as a
moderator, you are doing an excellent job.

Nonetheless do I think I added an important point and it is worth to
think about it (not in this thread of course).

Michael.




^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: Instead of pcase
  2023-11-21  2:42               ` Richard Stallman
  2023-11-21  5:14                 ` Jim Porter
  2023-11-21  5:34                 ` Yuri Khan
@ 2023-11-21 11:11                 ` Dmitry Gutov
  2023-11-21 15:38                   ` Michael Heerdegen
  2023-11-24  3:34                   ` Richard Stallman
  2023-11-24 17:29                 ` Lynn Winebarger
  2023-11-25  4:15                 ` Stefan Monnier
  4 siblings, 2 replies; 342+ messages in thread
From: Dmitry Gutov @ 2023-11-21 11:11 UTC (permalink / raw)
  To: rms; +Cc: philipk, emacs-devel

On 21/11/2023 04:42, Richard Stallman wrote:
> I uderstand that when you say it, but when I saw the line
> 
>>           > (`(,hookfun . (,start ,end ,collection . ,plist))
> I was not sure which part of the line that rule applies to.
> 
> In particular, what is the reason for the period and inner
> parenthsses?  Why doesn't the code say this?
> 
>>           > (`(,hookfun ,start ,end ,collection . ,plist)
> Would that be equiva;ent?

These are indeed equivalent.

The particular shape is chosen to follow how the data matched against 
was constructed in completion--capf-wrapper: (cons fun res). So it was 
for the ease of comprehension, actually.



^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: Instead of pcase
  2023-11-21  4:04                   ` Po Lu
@ 2023-11-21 11:27                     ` Dmitry Gutov
  2023-11-21 11:49                       ` Po Lu
  0 siblings, 1 reply; 342+ messages in thread
From: Dmitry Gutov @ 2023-11-21 11:27 UTC (permalink / raw)
  To: Po Lu; +Cc: Michael Heerdegen, Jim Porter, rms, emacs-devel

On 21/11/2023 06:04, Po Lu wrote:
>>> But don't argue that this cost does not exist, simply because it
>>> doesn't feel like a burden to you.
>> Did I?
> That's how it came across to me.  "The burden is immaterial since many
> categories of programmers do not perceive it as such" is not much
> different from "the burden does not exist," when the inferences drawn
> from both are identical, to wit: that pcase is fine as it is.

I never said that the cost doesn't exist. But one could ask whether it 
is a useful cost, overall, one that helps reduce the complexity of the 
code around it (one pays the cost when reading verbose code, too). Which 
might depend on how much one would have to work to understand to construct.

You provided statistics about your coworkers who are all used to working 
with low-level code, and then claimed that those should be 
representative of the Emacs userbase as a whole. I countered that.



^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: Instead of pcase
  2023-11-21 11:27                     ` Dmitry Gutov
@ 2023-11-21 11:49                       ` Po Lu
  0 siblings, 0 replies; 342+ messages in thread
From: Po Lu @ 2023-11-21 11:49 UTC (permalink / raw)
  To: Dmitry Gutov; +Cc: Michael Heerdegen, Jim Porter, rms, emacs-devel

Dmitry Gutov <dmitry@gutov.dev> writes:

> I never said that the cost doesn't exist. But one could ask whether it
> is a useful cost, overall, one that helps reduce the complexity of the
> code around it (one pays the cost when reading verbose code,
> too). Which might depend on how much one would have to work to
> understand to construct.
>
> You provided statistics about your coworkers who are all used to
> working with low-level code, and then claimed that those should be
> representative of the Emacs userbase as a whole. I countered that.

And I continue to disagree, because you never did cite any evidence to
the contrary.  It is very difficult to disabuse someone of a conviction
formed through observations of his surroundings without objective
evidence contradicting them, all the more so when others online also
concur.

Besides, IMHO exclusively linguistic goals are never worth their while
in Emacs Lisp.  It is an extension language, designed to be useful and
comprehensible to users without their setting themselves to its study.



^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: Instead of pcase
  2023-11-21 11:11                 ` Dmitry Gutov
@ 2023-11-21 15:38                   ` Michael Heerdegen
  2023-11-23  3:00                     ` Richard Stallman
  2023-11-24  3:34                   ` Richard Stallman
  1 sibling, 1 reply; 342+ messages in thread
From: Michael Heerdegen @ 2023-11-21 15:38 UTC (permalink / raw)
  To: emacs-devel

Dmitry Gutov <dmitry@gutov.dev> writes:

>> In particular, what is the reason for the period and inner
>> parenthsses?  Why doesn't the code say this?

This was a really good question.

> The particular shape is chosen to follow how the data matched against
> was constructed in completion--capf-wrapper: (cons fun res). So it was
> for the ease of comprehension, actually.

Indeed.  The backquote syntax allows to resemble the structure of the
matched list.  So it actually helps the readers understanding.

Stefan did not choose this syntax by accident.  On the contrary, it
helps writing readable code for complex cases.  Exactly what
higher-level constructs are good for: support writing and reading
complex code.

Michael.




^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: combining cond and let, to replace pcase.
  2023-11-18  3:03   ` combining cond and let, to replace pcase Richard Stallman
  2023-11-19 11:20     ` Michael Heerdegen
  2023-11-19 16:08     ` Axel Forsman
@ 2023-11-21 15:53     ` Michael Heerdegen
  2023-11-23  2:58     ` Richard Stallman
  3 siblings, 0 replies; 342+ messages in thread
From: Michael Heerdegen @ 2023-11-21 15:53 UTC (permalink / raw)
  To: Richard Stallman; +Cc: Spencer Baugh, emacs-devel

Richard Stallman <rms@gnu.org> writes:

> Here's an example to show what I have come up with along these lines:
>
> (cond* (:bind (x foobar) y z (foo 5) a)  ;; variables to bind, as in let
>        ;; I'm also thinking of using nil instead of :bind.
>
>        ;; t as condition means run this clause unconditionally
>        ;; then continue with next clause.
>        (t do-this-unconditionally-and-dont-stop...)
>
>        ;; Tests with a new function `match' which I'm going to work on next.
>        ((match x 'foo) ...)
>
>        ;; t in the last clause means the same as in previous clauses,
>        ;; but you can think of it as being the same as in `cond'.
>        (t do-this-as-last-resort)
>        )
>
> Rhe idea is that conf* does part of pcase's added functionality, and
> `match' will do the rest.  But it is not necessary to cram _all_ the
> additional matching functionality (to compare to pcase) into a single
> new function.  We could have more than one new function, eacn for its
> own kind of pattern matching.

I've also sometimes missed a cond-let.  I think the above example shows
something slightly different: binding is done in one branch, but the
bindings are visible in all (following?) branches (instead of only the
branch BODY).  So that's, at least in this example, more or less an
amalgamated let + cond.  The interesting part, the matching, is not
shown, so I only have a vague imagination of the whole picture.

Have you continued working on this approach in the meantime?


Michael.



^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: combining cond and let, to replace pcase.
  2023-11-19 21:36       ` Alan Mackenzie
@ 2023-11-21 16:14         ` Michael Heerdegen
  0 siblings, 0 replies; 342+ messages in thread
From: Michael Heerdegen @ 2023-11-21 16:14 UTC (permalink / raw)
  To: Alan Mackenzie; +Cc: Richard Stallman, Spencer Baugh, emacs-devel

Alan Mackenzie <acm@muc.de> writes:

> I may be mis-remembering, but I think it was you, Michael, who put in
> the work to fix these defects in pcase's doc string.  The result was
> far better than the original.

Only some work was done by me.

For me, personally (and only that) the documentation got worse.  That's
ok if it helps a lot of people.  If you have a more mathematical
background, the intention and the idea behind `pcase' are somewhat
shadowed now.

> An alternative here would have been to invent new reader macros
> instead of complicating and ambiguating ` and ,.

That would further shadow the idea.

It is obviously necessary to understand that design idea.  Seems this is
the major problem for most people.  We should probably do this in the
documentation if we have not yet.  Or did we?


Michael.



^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: Instead of pcase
  2023-11-21  2:01             ` Dmitry Gutov
@ 2023-11-22  2:59               ` Richard Stallman
  2023-11-22  3:29                 ` Emanuel Berg
  2023-11-22 11:58                 ` Dmitry Gutov
  0 siblings, 2 replies; 342+ messages in thread
From: Richard Stallman @ 2023-11-22  2:59 UTC (permalink / raw)
  To: Dmitry Gutov; +Cc: jemarch, emacs-devel

[[[ To any NSA and FBI agents reading my email: please consider    ]]]
[[[ whether defending the US Constitution against all enemies,     ]]]
[[[ foreign or domestic, requires you to follow Snowden's example. ]]]

  > In Lisps, most of the complexity simply moved to standard library 
  > (and/or other libraries as well).

This seems to presume a principle of "conservation of complexity", but
that is not so.  Complexity doesn't simply "move".  For example, pcase
replicates (with differences) complexity that already existed in
various Lisp functions and constructs.

-- 
Dr Richard Stallman (https://stallman.org)
Chief GNUisance of the GNU Project (https://gnu.org)
Founder, Free Software Foundation (https://fsf.org)
Internet Hall-of-Famer (https://internethalloffame.org)





^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: Instead of pcase
  2023-11-22  2:59               ` Richard Stallman
@ 2023-11-22  3:29                 ` Emanuel Berg
  2023-11-22 11:58                 ` Dmitry Gutov
  1 sibling, 0 replies; 342+ messages in thread
From: Emanuel Berg @ 2023-11-22  3:29 UTC (permalink / raw)
  To: emacs-devel

Richard Stallman wrote:

>> In Lisps, most of the complexity simply moved to standard
>> library (and/or other libraries as well).
>
> This seems to presume a principle of "conservation of
> complexity", but that is not so. Complexity doesn't simply
> "move".

I think what he means is, without libraries the complexity is
repeated in every file and in different ways with different
solutions often for the same situation.

With a library - the complexity is in one place alone, and all
the files using it conforms to the same interface.

-- 
underground experts united
https://dataswamp.org/~incal




^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: Instead of pcase
  2023-11-22  2:59               ` Richard Stallman
  2023-11-22  3:29                 ` Emanuel Berg
@ 2023-11-22 11:58                 ` Dmitry Gutov
  2023-11-24  3:38                   ` Richard Stallman
  1 sibling, 1 reply; 342+ messages in thread
From: Dmitry Gutov @ 2023-11-22 11:58 UTC (permalink / raw)
  To: rms; +Cc: jemarch, emacs-devel

On 22/11/2023 04:59, Richard Stallman wrote:
> [[[ To any NSA and FBI agents reading my email: please consider    ]]]
> [[[ whether defending the US Constitution against all enemies,     ]]]
> [[[ foreign or domestic, requires you to follow Snowden's example. ]]]
> 
>    > In Lisps, most of the complexity simply moved to standard library
>    > (and/or other libraries as well).
> 
> This seems to presume a principle of "conservation of complexity", but
> that is not so.

Not exactly. I just tried to explain that the notion of Lisp having 
"simple" syntax doesn't mean that everything about it can or should be 
just as simple.

> Complexity doesn't simply "move".  For example, pcase
> replicates (with differences) complexity that already existed in
> various Lisp functions and constructs.

Indeed. The goal there (and in such cases in general) is to concentrate 
specific bits of complexity inside advanced named constructs (functions 
or macros) that are designed in a way that reduces the total complexity 
in the code which uses them. Then you (roughly) only need to understand 
the construct (which is a fixed amount of complexity) and then every 
piece of code using it (as long as it's used appropriately) will incur 
lower mental overhead than if it were implemented using just the basic 
primitives. Reducing the total effort required to understand a series of 
such programs.



^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: Instead of pcase
  2023-11-20 15:32                     ` Michael Heerdegen
@ 2023-11-23  2:57                       ` Richard Stallman
  2023-11-24 17:14                         ` Dmitry Gutov
  2023-11-24 18:14                         ` Michael Heerdegen
  0 siblings, 2 replies; 342+ messages in thread
From: Richard Stallman @ 2023-11-23  2:57 UTC (permalink / raw)
  To: Michael Heerdegen; +Cc: emacs-devel

[[[ To any NSA and FBI agents reading my email: please consider    ]]]
[[[ whether defending the US Constitution against all enemies,     ]]]
[[[ foreign or domestic, requires you to follow Snowden's example. ]]]

  > This is the requirement: in some situations a code path should only be
  > chosen when a certain structure is present and certain requirements for
  > certain parts of the structure are fulfilled.  When you separate these
  > two things artificially you will make the thing more complicated, you
  > need to introduce extra bindings (for the tests) that the BODY doesn't
  > use, resulting in poorly readable code.

Would you be willing to show me two or thhree examples of this, so I
cam make sure those are natural enough in the framework I'm designing?

-- 
Dr Richard Stallman (https://stallman.org)
Chief GNUisance of the GNU Project (https://gnu.org)
Founder, Free Software Foundation (https://fsf.org)
Internet Hall-of-Famer (https://internethalloffame.org)





^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: Instead of pcase
  2023-11-20 14:35     ` Michael Heerdegen
@ 2023-11-23  2:57       ` Richard Stallman
  0 siblings, 0 replies; 342+ messages in thread
From: Richard Stallman @ 2023-11-23  2:57 UTC (permalink / raw)
  To: Michael Heerdegen; +Cc: emacs-devel

[[[ To any NSA and FBI agents reading my email: please consider    ]]]
[[[ whether defending the US Constitution against all enemies,     ]]]
[[[ foreign or domestic, requires you to follow Snowden's example. ]]]

  > > Would you like to help design matching functions to do the same jobs
  > > that pcase does?

  > With pleasure, I'll try to do my best.

Thank you.

  > > I would like to make it possible to combine various matching and
  > > destructuring functions using `and' and `or' (plus any other Lisp
  > > functions you like).

  > Would this still be based on pcase or be something completely new?

It would become part of the cond* idea that I previously posted the
first draft of.  I posted a newer version today.


-- 
Dr Richard Stallman (https://stallman.org)
Chief GNUisance of the GNU Project (https://gnu.org)
Founder, Free Software Foundation (https://fsf.org)
Internet Hall-of-Famer (https://internethalloffame.org)





^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: combining cond and let, to replace pcase.
  2023-11-18  3:03   ` combining cond and let, to replace pcase Richard Stallman
                       ` (2 preceding siblings ...)
  2023-11-21 15:53     ` Michael Heerdegen
@ 2023-11-23  2:58     ` Richard Stallman
  2023-11-23  7:02       ` Tomas Hlavaty
                         ` (3 more replies)
  3 siblings, 4 replies; 342+ messages in thread
From: Richard Stallman @ 2023-11-23  2:58 UTC (permalink / raw)
  To: emacs-devel

[[[ To any NSA and FBI agents reading my email: please consider    ]]]
[[[ whether defending the US Constitution against all enemies,     ]]]
[[[ foreign or domestic, requires you to follow Snowden's example. ]]]

I've done more work on designing `cond*'; here is what I have now.
Please send me constructive suggestions, including for features you
suggest adding.

(cond* 
       ;; Same as a clause in `cond',
       (CONDITION
        do-this-if-CONDITION-then-exit...)

       ;; Variables to bind, as in let
       (:bind (x foobar) y z (foo 5) a)
       ;; Bindings continue in effect.

       ;; t as condition means run this clause unconditionally
       ;; then always continue with next clause.
       (t do-this-unconditionally-and-dont-stop...)

       ;; Extracts substructure and binds variables around the rest
       ;; of the cond*.
       (:match (`(expt ,foo ,bar) x)
        do-this-if-it-matched-then-exit...)
       ;; Bindings continue in effect.

       ;; Like above but always falls thru to next clause.
       (:match (`(expt ,foo ,bar) x))
       ;; Bindings continue in effect.

       ;; t in the last clause means the same as in previous clauses,
       ;; but you can think of it as being the same as in `cond'.
       (t do-this-as-last-resort...)
       )

Here are three macros that would be useful as conditions in `cond*'
but can also be used elsewhere.

(match PATTERN VALUE)
       This is a macro.
       PATTERN is a backquote form which specifies which parts of
       VALUE should be fixed.  For instance
       (match `(+ (expt nil nil)) (get-complex-list))
       would decompose the result of (get-complex-list) and check
       for `+' and `expt' in it.

       PATTERN will not be evaluated, just used as guidance when the
       `match' form is macroexpanded.

       If PATTERN includes substitutions, it will virtually perform
       those substitutions and compare parts of VALUE against them.
       (match `(foo ,foo) x) compares (car x) with `foo' and
       compares (cadr x) with the value of foo.

       `match' can also handle vectors and maybe some other kinds of
       structures.

(match-set PATTERN VALUE)
       This is a macro.
       PATTERN is a backquote form which specifies which parts of
       VALUE to match and parts to extract and store.  For instance
       (match-set `(+ ,y ,z) (get-complex-list))
       would decompose the result of (get-complex-list), verify the car,
       and set y and z.

       PATTERN will not be evaluated, just used as guidance when the
       `match-set' form is macroexpanded, producing code like this:

       (if (eq (car value) '+)
           (progn
             (setq y (car (cadr value)) z (cadr (cadr value)))
             t))

       `match' can also handle vectors and maybe some other kinds of
       structures.

(match-bind PATTERN VALUE BODY...)
       Much like `match-set', except that instead of setting the
       variables found in PATTERN, it let-binds them and runs BODY
       with those bindings.

-- 
Dr Richard Stallman (https://stallman.org)
Chief GNUisance of the GNU Project (https://gnu.org)
Founder, Free Software Foundation (https://fsf.org)
Internet Hall-of-Famer (https://internethalloffame.org)





^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: Instead of pcase
  2023-11-21 15:38                   ` Michael Heerdegen
@ 2023-11-23  3:00                     ` Richard Stallman
  0 siblings, 0 replies; 342+ messages in thread
From: Richard Stallman @ 2023-11-23  3:00 UTC (permalink / raw)
  To: Michael Heerdegen; +Cc: emacs-devel

[[[ To any NSA and FBI agents reading my email: please consider    ]]]
[[[ whether defending the US Constitution against all enemies,     ]]]
[[[ foreign or domestic, requires you to follow Snowden's example. ]]]

  > > The particular shape is chosen to follow how the data matched against
  > > was constructed in completion--capf-wrapper: (cons fun res). So it was
  > > for the ease of comprehension, actually.

  > Indeed.  The backquote syntax allows to resemble the structure of the
  > matched list.  So it actually helps the readers understanding.

Maybe it helps someone understand some code in another context,
but in did not help me understand that example.

-- 
Dr Richard Stallman (https://stallman.org)
Chief GNUisance of the GNU Project (https://gnu.org)
Founder, Free Software Foundation (https://fsf.org)
Internet Hall-of-Famer (https://internethalloffame.org)





^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: combining cond and let, to replace pcase.
  2023-11-23  2:58     ` Richard Stallman
@ 2023-11-23  7:02       ` Tomas Hlavaty
  2023-11-26  3:14         ` Richard Stallman
  2023-11-23  8:58       ` Manuel Giraud via Emacs development discussions.
                         ` (2 subsequent siblings)
  3 siblings, 1 reply; 342+ messages in thread
From: Tomas Hlavaty @ 2023-11-23  7:02 UTC (permalink / raw)
  To: rms, emacs-devel

On Wed 22 Nov 2023 at 21:58, Richard Stallman <rms@gnu.org> wrote:
> (cond* 
>        ;; Same as a clause in `cond',
>        (CONDITION
>         do-this-if-CONDITION-then-exit...)
>
>        ;; Variables to bind, as in let
>        (:bind (x foobar) y z (foo 5) a)
>        ;; Bindings continue in effect.

This seems nicer:

(if CONDITION
    do-this-if-CONDITION-then-exit...
    (let ((x foobar) y z (foo 5) a)
      ...))

Are there other macros where bindings continue in effect cond* style?

It looks like everybody is trying to design a "do it all super-macro"
instead of using something like cl-destructuring-bind.

>        (:match (`(expt ,foo ,bar) x)

That looks like writing (let (`(,foo 42)) ...)

Are there other macros where unquote marks variable name?



^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: combining cond and let, to replace pcase.
  2023-11-23  2:58     ` Richard Stallman
  2023-11-23  7:02       ` Tomas Hlavaty
@ 2023-11-23  8:58       ` Manuel Giraud via Emacs development discussions.
  2023-11-26  3:14         ` Richard Stallman
  2023-11-24  3:08       ` Daniel Semyonov
  2023-11-25  5:11       ` Stefan Monnier via Emacs development discussions.
  3 siblings, 1 reply; 342+ messages in thread
From: Manuel Giraud via Emacs development discussions. @ 2023-11-23  8:58 UTC (permalink / raw)
  To: Richard Stallman; +Cc: emacs-devel

Richard Stallman <rms@gnu.org> writes:

> [[[ To any NSA and FBI agents reading my email: please consider    ]]]
> [[[ whether defending the US Constitution against all enemies,     ]]]
> [[[ foreign or domestic, requires you to follow Snowden's example. ]]]
>
> I've done more work on designing `cond*'; here is what I have now.
> Please send me constructive suggestions, including for features you
> suggest adding.

Only gut feelings here, but fall thru with bindings by default and
multiple t may surprise users and lead to not simple to debug code.
-- 
Manuel Giraud



^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: combining cond and let, to replace pcase.
  2023-11-23  2:58     ` Richard Stallman
  2023-11-23  7:02       ` Tomas Hlavaty
  2023-11-23  8:58       ` Manuel Giraud via Emacs development discussions.
@ 2023-11-24  3:08       ` Daniel Semyonov
  2023-11-24  3:26         ` Daniel Semyonov
  2023-11-25  2:59         ` Richard Stallman
  2023-11-25  5:11       ` Stefan Monnier via Emacs development discussions.
  3 siblings, 2 replies; 342+ messages in thread
From: Daniel Semyonov @ 2023-11-24  3:08 UTC (permalink / raw)
  To: rms; +Cc: emacs-devel

[-- Attachment #1: Type: text/plain, Size: 1820 bytes --]

>>>>> Richard Stallman writes:

 > I've done more work on designing `cond*'; here is what I have now.
 > Please send me constructive suggestions, including for features you
 > suggest adding.

I think either the name should be changed or the behavior of t as a
condition should be the same as in 'cond', as IMO it could lead to
confusion. Maybe ':always' or ':continue' could be used instead?

Other than that this seems very simple and easy to understand, I would
honestly much prefer this over 'pcase'.

 > Here are three macros that would be useful as conditions in `cond*'
 > but can also be used elsewhere.

These also seem nice, but they make the ':match' condition
almost pointless? AFAIU, the following should be equivalent:

(cond* (:bind foo bar (x foobar))
 ;; IMO changing t to ':always' would make it very clear what's
 ;; going on here.
 (t (match-set `(a ,foo ,bar) x))
 ((match-set `(b ,foo ,bar) x)
 ;; do stuff and exit
 )
 ;; more conditions...
 )

(cond* (:bind (x foobar))
 (:match (`(a ,foo ,bar) x))
 (:match (`(b ,foo ,bar) x)
 ;; do stuff and exit...
 )
 ;; more conditions...
 )

The only usecase for ':match' (which can't really be fulfilled by the
macros) is binding "new" variables (which haven't been bound using
':bind' beforehand), but I think requiring an explicit ':bind' is more
clear, and would make it easier to quickly identify local variable
names. It could also be better for people new to ELisp eventually, since
these macros would be more likely familiar to them already (due to their
potential usage outside of 'cond*') when compared to ':match'.

And a minor nitpick, I think it would be better to rename 'match-bind'
to 'match-let', to mirror other macros like 'if-let' (maybe even change
':bind' to ':let').

Regards,
Daniel

[-- Attachment #2: Type: text/html, Size: 2013 bytes --]

^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: combining cond and let, to replace pcase.
  2023-11-24  3:08       ` Daniel Semyonov
@ 2023-11-24  3:26         ` Daniel Semyonov
  2023-11-25  2:59         ` Richard Stallman
  1 sibling, 0 replies; 342+ messages in thread
From: Daniel Semyonov @ 2023-11-24  3:26 UTC (permalink / raw)
  To: emacs-devel, rms

Sorry, I sent the last mail as HTML by accident, here's a more readable version of the code:

(cond* (:bind foo bar (x foobar))
       ;; IMO changing t to ':always' would make it very clear what's
       ;; going on here.
       (t (match-set `(a ,foo ,bar) x))
       ((match-set `(b ,foo ,bar) x)
        ;; do stuff and exit
        )
       ;; more conditions...
       )

(cond* (:bind (x foobar))
       (:match (`(a ,foo ,bar) x))
       (:match (`(b ,foo ,bar) x)
               ;; do stuff and exit...
               )
       ;; more conditions...
       )



^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: Instead of pcase
  2023-11-21 11:11                 ` Dmitry Gutov
  2023-11-21 15:38                   ` Michael Heerdegen
@ 2023-11-24  3:34                   ` Richard Stallman
  2023-11-24  4:30                     ` Jim Porter
  2023-11-24 17:01                     ` Dmitry Gutov
  1 sibling, 2 replies; 342+ messages in thread
From: Richard Stallman @ 2023-11-24  3:34 UTC (permalink / raw)
  To: Dmitry Gutov; +Cc: philipk, emacs-devel

[[[ To any NSA and FBI agents reading my email: please consider    ]]]
[[[ whether defending the US Constitution against all enemies,     ]]]
[[[ foreign or domestic, requires you to follow Snowden's example. ]]]

  > >>           > (`(,hookfun . (,start ,end ,collection . ,plist))
  > > I was not sure which part of the line that rule applies to.
  > > 
  > >>           > (`(,hookfun ,start ,end ,collection . ,plist)
  > > Would that be equiva;ent?

I as a reader, trying to understand what that pcase construct did, did
not know they would be equivalent.  So this specific piece of
cleverness specifically interfered with my understanding that example
and therefore with my trying to understand pcase.

  > The particular shape is chosen to follow how the data matched against 
  > was constructed in completion--capf-wrapper: (cons fun res). So it was 
  > for the ease of comprehension, actually.

I believe the assertion that this was intended to achieve that result.
Whether it did achieve that, for some users, I don't know.  But I can
testify that, for this reader, it had the opposite effect.

-- 
Dr Richard Stallman (https://stallman.org)
Chief GNUisance of the GNU Project (https://gnu.org)
Founder, Free Software Foundation (https://fsf.org)
Internet Hall-of-Famer (https://internethalloffame.org)





^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: Instead of pcase
  2023-11-22 11:58                 ` Dmitry Gutov
@ 2023-11-24  3:38                   ` Richard Stallman
  0 siblings, 0 replies; 342+ messages in thread
From: Richard Stallman @ 2023-11-24  3:38 UTC (permalink / raw)
  To: Dmitry Gutov; +Cc: jemarch, emacs-devel

[[[ To any NSA and FBI agents reading my email: please consider    ]]]
[[[ whether defending the US Constitution against all enemies,     ]]]
[[[ foreign or domestic, requires you to follow Snowden's example. ]]]

  > Indeed. The goal there (and in such cases in general) is to concentrate 
  > specific bits of complexity inside advanced named constructs (functions 
  > or macros) that are designed in a way that reduces the total complexity 
  > in the code which uses them.

I think you and I mean different things when we say "complexity".
In this conversation, we are miscommunicating.

To replace a pcase call with direct use of old Emacs Lisp constructs
would make code that is more verbose.  That could be considered a kind
of complexity.

But I'm talking about the complexity of the language that the code is
written in.  pcase code is written in a separate "domain-specific
language", and the complexity of that language adds to the complexity
of the Emacs Lisp language.  But it still contains all those same old
Emacs Lisp constructs.  pcase does not replace any of that complexity;
it adds additional complexity to the language.

I hope that cond* will do the same kind of code-simplification that
pcase does, while adding much less to the complexity of the lsnguage
that the code is written in.

-- 
Dr Richard Stallman (https://stallman.org)
Chief GNUisance of the GNU Project (https://gnu.org)
Founder, Free Software Foundation (https://fsf.org)
Internet Hall-of-Famer (https://internethalloffame.org)





^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: Instead of pcase
  2023-11-24  3:34                   ` Richard Stallman
@ 2023-11-24  4:30                     ` Jim Porter
  2023-11-24  7:45                       ` Eli Zaretskii
  2023-11-25  3:08                       ` Emanuel Berg
  2023-11-24 17:01                     ` Dmitry Gutov
  1 sibling, 2 replies; 342+ messages in thread
From: Jim Porter @ 2023-11-24  4:30 UTC (permalink / raw)
  To: rms, Dmitry Gutov; +Cc: philipk, emacs-devel

On 11/23/2023 7:34 PM, Richard Stallman wrote:
>    > >>           > (`(,hookfun . (,start ,end ,collection . ,plist))
>    > > I was not sure which part of the line that rule applies to.
>    > >
>    > >>           > (`(,hookfun ,start ,end ,collection . ,plist)
>    > > Would that be equiva;ent?
> 
> I as a reader, trying to understand what that pcase construct did, did
> not know they would be equivalent.  So this specific piece of
> cleverness specifically interfered with my understanding that example
> and therefore with my trying to understand pcase.

For cases like this, I hope to (at least partially) address it with 
better documentation. I'm not sure we can expect every instance of 
'pcase' in the Emacs codebase to be a good teachable example for how to 
use 'pcase', but I do think we could achieve that with shortdocs. The 
shortdocs could start small with almost-trivial examples, and then build 
up to more-complex forms that show how the pieces interact.

Broadly, my goal would be that anyone who already knows Lisp could load 
up the shortdocs for pcase and get the hang of 95% of it in a few minutes.

(I also think we could improve the manuals and the docstring, but I 
think 'pcase' is a great candidate for teaching by example. The shortdoc 
system seems ideal for that.)



^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: Instead of pcase
  2023-11-24  4:30                     ` Jim Porter
@ 2023-11-24  7:45                       ` Eli Zaretskii
  2023-11-25  3:08                       ` Emanuel Berg
  1 sibling, 0 replies; 342+ messages in thread
From: Eli Zaretskii @ 2023-11-24  7:45 UTC (permalink / raw)
  To: Jim Porter; +Cc: rms, dmitry, philipk, emacs-devel

> Date: Thu, 23 Nov 2023 20:30:27 -0800
> Cc: philipk@posteo.net, emacs-devel@gnu.org
> From: Jim Porter <jporterbugs@gmail.com>
> 
> For cases like this, I hope to (at least partially) address it with 
> better documentation. I'm not sure we can expect every instance of 
> 'pcase' in the Emacs codebase to be a good teachable example for how to 
> use 'pcase', but I do think we could achieve that with shortdocs. The 
> shortdocs could start small with almost-trivial examples, and then build 
> up to more-complex forms that show how the pieces interact.

It depends on what you mean by "almost-trivial examples", but in
general I find trivial examples to be at best of very limited value.
First, where the use of 'pcase' is trivial, we should usually not use
'pcase' at all, but the equivalent constructs that are easier to read
and understand.  More importantly, trivial examples (the ones I have
in mind) don't add anything to the written documentation, and thus
neither help you better understand the documentation's subtle and
obscure corners nor ease specific practical tasks of writing code that
uses 'pcase' for specific purposes.  The latter is an explicit goal of
shortdocs, why we have it in the first place, so having trivial
examples there for such advanced and flexible constructs defeats its
very purpose, IMO.

> (I also think we could improve the manuals and the docstring, but I 
> think 'pcase' is a great candidate for teaching by example. The shortdoc 
> system seems ideal for that.)

I disagree that the shortdoc system is intended to teach by example.
Such a system must have many explanations for each example, and
shortdoc provides only a terse single-sentence description of each
example.  From where I stand, shortdoc is supposed to show real-life
examples of doing non-trivial jobs, with the intent that given a
relevant example, the reader could then go back to the documentation
and say: "ah, so that's what they meant when they talked about
so-and-so!"  IOW, shortdoc is NOT supposed to replace the
documentation, only to be a collection of examples that illustrate the
documentation.



^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: Instead of pcase
  2023-11-24  3:34                   ` Richard Stallman
  2023-11-24  4:30                     ` Jim Porter
@ 2023-11-24 17:01                     ` Dmitry Gutov
  1 sibling, 0 replies; 342+ messages in thread
From: Dmitry Gutov @ 2023-11-24 17:01 UTC (permalink / raw)
  To: rms; +Cc: philipk, emacs-devel

On 24/11/2023 05:34, Richard Stallman wrote:
>    > >>           > (`(,hookfun . (,start ,end ,collection . ,plist))
>    > > I was not sure which part of the line that rule applies to.
>    > >
>    > >>           > (`(,hookfun ,start ,end ,collection . ,plist)
>    > > Would that be equiva;ent?
> 
> I as a reader, trying to understand what that pcase construct did, did
> not know they would be equivalent.  So this specific piece of
> cleverness specifically interfered with my understanding that example
> and therefore with my trying to understand pcase.

Most of the semantics-conveying tricks with advanced tools require a 
certain level of familiarity with the tool in question.

Much like how one has to master a foreign language on a certain level to 
understand a lot of idioms. But then those idioms help understand each 
other better and more comprehensively.



^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: Instead of pcase
  2023-11-23  2:57                       ` Richard Stallman
@ 2023-11-24 17:14                         ` Dmitry Gutov
  2023-11-27  3:09                           ` Richard Stallman
  2023-11-28  2:44                           ` Richard Stallman
  2023-11-24 18:14                         ` Michael Heerdegen
  1 sibling, 2 replies; 342+ messages in thread
From: Dmitry Gutov @ 2023-11-24 17:14 UTC (permalink / raw)
  To: rms, Michael Heerdegen; +Cc: emacs-devel

On 23/11/2023 04:57, Richard Stallman wrote:
>    > This is the requirement: in some situations a code path should only be
>    > chosen when a certain structure is present and certain requirements for
>    > certain parts of the structure are fulfilled.  When you separate these
>    > two things artificially you will make the thing more complicated, you
>    > need to introduce extra bindings (for the tests) that the BODY doesn't
>    > use, resulting in poorly readable code.
> 
> Would you be willing to show me two or thhree examples of this, so I
> cam make sure those are natural enough in the framework I'm designing?

I suggest you try rewriting the definition of completion-help-at-point 
using your alternative construct.

We just discussed what the pcase clauses there do, and they are small 
enough so this won't be a lot of work, while at the same time they 
exhibit several of the important features of pcase.



^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: Instead of pcase
  2023-11-21  2:42               ` Richard Stallman
                                   ` (2 preceding siblings ...)
  2023-11-21 11:11                 ` Dmitry Gutov
@ 2023-11-24 17:29                 ` Lynn Winebarger
  2023-11-28  2:44                   ` Richard Stallman
  2023-11-25  4:15                 ` Stefan Monnier
  4 siblings, 1 reply; 342+ messages in thread
From: Lynn Winebarger @ 2023-11-24 17:29 UTC (permalink / raw)
  To: Richard Stallman; +Cc: Dmitry Gutov, Philip Kaludercic, emacs-devel

[-- Attachment #1: Type: text/plain, Size: 1380 bytes --]

On Mon, Nov 20, 2023, 9:42 PM Richard Stallman <rms@gnu.org> wrote:

>
>   > > They contain code that looks like Lisp but does not have the same
>   > > semantic rules as Lisp.
>
>   > Yes: it's a domain-specific language.
>
> THat is why pcase adds to the total complexity of Emacs Lisp: because
> it incorporates a domain-specific language.  (I called it a "little
> lajguage".)
>
>   > To interpret those backquotes and commas, one can imagine that the
> they
>   > do the inverse of the usual.
>
> I uderstand that when you say it, but when I saw the line
>
> >          > (`(,hookfun . (,start ,end ,collection . ,plist))
>
> I was not sure which part of the line that rule applies to.
>
> In particular, what is the reason for the period and inner
> parenthsses?  Why doesn't the code say this?


> >          > (`(,hookfun ,start ,end ,collection . ,plist)
>
> Would that be equiva;ent?
>
> I could not assume the inner parenthsses were unnecessary.  Maybe
> there was a conventiob by which they change the meaning.
> I did not know.


I haven't seen anyone point this out yet, but they have to be equivalent.
The reader constructs the same data structure for those concrete
expressions (text) before the pcase macro is ever evaluated.

I would think the author is simply emphasizing that they are parsing an
entity in an association list for which hookfun is a key.

Lynn

[-- Attachment #2: Type: text/html, Size: 2159 bytes --]

^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: Instead of pcase
  2023-11-23  2:57                       ` Richard Stallman
  2023-11-24 17:14                         ` Dmitry Gutov
@ 2023-11-24 18:14                         ` Michael Heerdegen
  2023-11-24 18:35                           ` Dmitry Gutov
  2023-11-27  3:14                           ` Richard Stallman
  1 sibling, 2 replies; 342+ messages in thread
From: Michael Heerdegen @ 2023-11-24 18:14 UTC (permalink / raw)
  To: Richard Stallman; +Cc: emacs-devel

Richard Stallman <rms@gnu.org> writes:

> Would you be willing to show me two or thhree examples of this, so I
> cam make sure those are natural enough in the framework I'm designing?

I would suggest to look at some more complex cases where several `pcase'
features appear combined.  Making these complex cases not harder
to read is important: a suitable replacement of `pcase' should be able
to express what the code is doing in a similarly descriptive manner.
[ I'm still skeptical there is so much room for improvement I must admit. ]

I collected some more or less random examples that combine several
`pcase' features and are not too long:

  ffap-other-window
  menu-bar-item-at-x
  completion-at-point
  byte-optimize-funcall
  byte-optimize-letX
  cl-typep

I can help with the translation if this is desired.  `macroexpand-1' can
also help but of course it's more practical for the smaller examples.

I think it would be good to try to translate such examples into the
to-be-invented language before actually implementing all the details
(top-down).


Michael.



^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: Instead of pcase
  2023-11-24 18:14                         ` Michael Heerdegen
@ 2023-11-24 18:35                           ` Dmitry Gutov
  2023-11-27  3:14                           ` Richard Stallman
  1 sibling, 0 replies; 342+ messages in thread
From: Dmitry Gutov @ 2023-11-24 18:35 UTC (permalink / raw)
  To: Michael Heerdegen, Richard Stallman; +Cc: emacs-devel

On 24/11/2023 20:14, Michael Heerdegen wrote:
>    byte-optimize-letX
>    cl-typep

Nice examples. These two in particular showcase the benefit of terseness 
in the matching syntax: you can grasp the structure of the whole 
complicated function quickly when it fits on one screen.



^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: combining cond and let, to replace pcase.
  2023-11-24  3:08       ` Daniel Semyonov
  2023-11-24  3:26         ` Daniel Semyonov
@ 2023-11-25  2:59         ` Richard Stallman
  1 sibling, 0 replies; 342+ messages in thread
From: Richard Stallman @ 2023-11-25  2:59 UTC (permalink / raw)
  To: Daniel Semyonov; +Cc: emacs-devel

[[[ To any NSA and FBI agents reading my email: please consider    ]]]
[[[ whether defending the US Constitution against all enemies,     ]]]
[[[ foreign or domestic, requires you to follow Snowden's example. ]]]

  > And a minor nitpick, I think it would be better to rename 'match-bind'
  > to 'match-let', to mirror other macros like 'if-let' (maybe even change
  > ':bind' to ':let').

I am not sure.  `if-let' uses a list of variables, similar to (but not
identical to) what `let*' uses.  `match-bind' uses a patter to control
which variables to bind.  I think that dissimilar names will make this
clearer than similar names would do.
-- 
Dr Richard Stallman (https://stallman.org)
Chief GNUisance of the GNU Project (https://gnu.org)
Founder, Free Software Foundation (https://fsf.org)
Internet Hall-of-Famer (https://internethalloffame.org)





^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: Instead of pcase
  2023-11-24  4:30                     ` Jim Porter
  2023-11-24  7:45                       ` Eli Zaretskii
@ 2023-11-25  3:08                       ` Emanuel Berg
  1 sibling, 0 replies; 342+ messages in thread
From: Emanuel Berg @ 2023-11-25  3:08 UTC (permalink / raw)
  To: emacs-devel

Jim Porter wrote:

> For cases like this, I hope to (at least partially) address
> it with better documentation. I'm not sure we can expect
> every instance of 'pcase' in the Emacs codebase to be a good
> teachable example for how to use 'pcase', but I do think we
> could achieve that with shortdocs. The shortdocs could start
> small with almost-trivial examples, and then build up to
> more-complex forms that show how the pieces interact.
>
> Broadly, my goal would be that anyone who already knows Lisp
> could load up the shortdocs for pcase and get the hang of
> 95% of it in a few minutes.
>
> (I also think we could improve the manuals and the
> docstring, but I think 'pcase' is a great candidate for
> teaching by example. The shortdoc system seems ideal
> for that.)

One could make the first examples as easy as possible to show
all the aspects of pcase use, this is how you do this, this is
how you do that, and so on, the bunch. It would include
terminology but only terminology that is visible in
that example.

Then there could be examples that included combinations of
such aspects, this is helpful to assimilate the
previous examples.

After that, actual but typical use cases from the
Emacs source.

After that, gray areas, weird border cases and so on, also
from the Emacs source (if we can find them - if not, all the
better).

-- 
underground experts united
https://dataswamp.org/~incal




^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: Complex SPEC for variables/customization like font-lock-keywords/org-capture-templates/etc
  2023-11-17  8:54         ` Complex SPEC for variables/customization like font-lock-keywords/org-capture-templates/etc (was: Instead of pcase) Ihor Radchenko
@ 2023-11-25  4:03           ` Stefan Monnier
  0 siblings, 0 replies; 342+ messages in thread
From: Stefan Monnier @ 2023-11-25  4:03 UTC (permalink / raw)
  To: emacs-devel; +Cc: monnier

> Or font-lock-keywords... Last time I were seriously developing new
> keywords, I had to do it by trial-and-error and even examine
> font-lock sources.
[...]
> I do not know a good solution to the above, and thus would like to
> discuss this problem.
>
> Some possible ideas:
>
> 1. Provide some universal mechanism for type-validation of variables.
>    Something similar to :type spec in defcustom, but for Elisp
>    variables. This will at least catch invalid values.

IME, the problem usually stems from a confusion between code and data:
`font-lock-keywords` should hold code (i.e. something like a function)
rather than nested-lists-with-special-structure.
We could then provide some kind of macro to make it easier to define
these functions.

That's what I tried to do with `syntax-propertize-rules`, which is
otherwise very similar to the previous `font-lock-syntactic-keywords`.
That's also what I did with `bindat-type`.

This has the advantage that the macro can make various sanity checks
(and hence detect some of the possible errors), and that we can (to
some extent) Edebug the result.

I intended to try and provide a similar replacement facility for
`font-lock-keywords`, but haven't gotten to it.

> 3. Enhance eldoc to show a tip about variable value structure, similar
>    to what is done for function arguments.

It doesn't really work for `bindat-type`, but the use of macros should
make it easier because the code tells us reliably  that this is a Bindat
type whereas nothing in the declaration of (defvar
my-font-lock-keywords-1 <FOO>) that the <FOO> nested lists are meant to
be font-lock keywords (unless we use heuristics based on var names,
which quickly become ugly and brittle).


        Stefan




^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: Instead of pcase
  2023-11-21  2:42               ` Richard Stallman
                                   ` (3 preceding siblings ...)
  2023-11-24 17:29                 ` Lynn Winebarger
@ 2023-11-25  4:15                 ` Stefan Monnier
  2023-11-27  3:12                   ` Richard Stallman
  4 siblings, 1 reply; 342+ messages in thread
From: Stefan Monnier @ 2023-11-25  4:15 UTC (permalink / raw)
  To: emacs-devel; +Cc: monnier

>   > To interpret those backquotes and commas, one can imagine that the they
>   > do the inverse of the usual.
> I uderstand that when you say it, but when I saw the line
>
>          (`(,hookfun . (,start ,end ,collection . ,plist))
>
> I was not sure which part of the line that rule applies to.

Interesting.  I find this one to be very straightforward.
The previous line with the `and` and the `pred` is the more problematic one.

> In particular, what is the reason for the period and inner
> parenthsses?

Because (HOOKFUN . VALUE) is what is returned by the `run-hook-wrapped`
function and (,START ,END ,COLLECTION . ,PLIST) is the format of the
value returned by the hook's functions.
IOW, a merely stylistic choice.

>  Why doesn't the code say this?
>
>          (`(,hookfun ,start ,end ,collection . ,plist)
>
> Would that be equiva;ent?

Interesting.  `pcase` is a macro, so it does not see the above
characters, it only sees the resulting Sexp returned by the Lisp reader,
and as you may remember, the reader returns *exactly* the same Sexp
for the above two lines of text.
So `pcase` would be hard pressed to make those two *not* equivalent :-)


        Stefan




^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: Instead of pcase
  2023-11-19 19:31                   ` Eric Abrahamsen
@ 2023-11-25  4:23                     ` Stefan Monnier via Emacs development discussions.
  2023-11-27  3:12                       ` Richard Stallman
  0 siblings, 1 reply; 342+ messages in thread
From: Stefan Monnier via Emacs development discussions. @ 2023-11-25  4:23 UTC (permalink / raw)
  To: emacs-devel

> I agree that once you introduce guards/predicates, pcase gets ugly fast,

Yeah, it's also my experience (tho a single `pred` is usually OK as long as you
don't also need to bind the value, thus forcing you into the ugly
`(and (pred PRED) VAR)` thingy).

I have toyed with the idea of providing the guards separately from the
patterns, but not enough to find something satisfactory.


        Stefan




^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: Instead of pcase
  2023-11-16 20:16   ` Tomas Hlavaty
  2023-11-16 21:37     ` [External] : " Drew Adams
@ 2023-11-25  4:34     ` Stefan Monnier via Emacs development discussions.
  2023-11-25  8:53       ` Eli Zaretskii
  1 sibling, 1 reply; 342+ messages in thread
From: Stefan Monnier via Emacs development discussions. @ 2023-11-25  4:34 UTC (permalink / raw)
  To: emacs-devel

> (let ((exp (if t '(foo . "str") '(bar . 7))))
>   (cl-case (car exp)
>     (foo
>      (when-let ((d (cdr exp)))
>        (concat "str" val)))
>     (bar
>      (when-let ((d (cdr exp)))
>        (1+ val)))))

AKA

    (let ((exp (if t '(foo . "str") '(bar . 7))))
      (case (car exp)
        ('foo
         (when-let ((d (cdr exp)))
           (concat "str" val)))
        ('bar
         (when-let ((d (cdr exp)))
           (1+ val)))))

Funnily enough this quoting of the values against which we want to match
is so natural for coders not familiar with `cl-case` that we went
through some efforts to try and detect their mis-use.

So at least for some coders, in the above case, the `pcase` syntax is the
more natural one :-)


        Stefan




^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: combining cond and let, to replace pcase.
  2023-11-19 18:10       ` Tomas Hlavaty
@ 2023-11-25  4:45         ` Stefan Monnier via Emacs development discussions.
  2023-11-28 15:31           ` João Távora
  0 siblings, 1 reply; 342+ messages in thread
From: Stefan Monnier via Emacs development discussions. @ 2023-11-25  4:45 UTC (permalink / raw)
  To: emacs-devel

> that is why cl-loop and maybe pcase are "ugly"
> one heuristic could be if autodoc can display something useful

I suspect it would be difficult to do for `cl-loop` (would require heavy
hacking on `cl-loop` itself), but for `pcase` (and `bindat-type`)
I think it would not be too terribly hard to add Eldoc support, and it
would be definitely a nice improvement.


        Stefan




^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: combining cond and let, to replace pcase.
  2023-11-23  2:58     ` Richard Stallman
                         ` (2 preceding siblings ...)
  2023-11-24  3:08       ` Daniel Semyonov
@ 2023-11-25  5:11       ` Stefan Monnier via Emacs development discussions.
  2023-11-27  3:11         ` Richard Stallman
  2023-11-27  3:11         ` Richard Stallman
  3 siblings, 2 replies; 342+ messages in thread
From: Stefan Monnier via Emacs development discussions. @ 2023-11-25  5:11 UTC (permalink / raw)
  To: emacs-devel

> (cond* 
[...]
>        ;; Extracts substructure and binds variables around the rest
>        ;; of the cond*.
>        (:match (`(expt ,foo ,bar) x)
>         do-this-if-it-matched-then-exit...)
>        ;; Bindings continue in effect.

Which bindings?  Presumably when we continue the match failed, so `foo`
and `bar` don't have any meaningful value to take, AFAICT.
IOW we're continuing with the bindings that existed *before* the
`:match`, but not with the bindings introduced by the `:match`, right?

>        ;; Like above but always falls thru to next clause.
>        (:match (`(expt ,foo ,bar) x))
>        ;; Bindings continue in effect.

What happens if `(car x)` is not equal to `expt` or if `x` is a string?

> (match PATTERN VALUE)
>        This is a macro.
>        PATTERN is a backquote form which specifies which parts of
>        VALUE should be fixed.  For instance
>        (match `(+ (expt nil nil)) (get-complex-list))
>        would decompose the result of (get-complex-list) and check
>        for `+' and `expt' in it.
>
>        PATTERN will not be evaluated, just used as guidance when the
>        `match' form is macroexpanded.
>
>        If PATTERN includes substitutions, it will virtually perform
>        those substitutions and compare parts of VALUE against them.
>        (match `(foo ,foo) x) compares (car x) with `foo' and
>        compares (cadr x) with the value of foo.
>
>        `match' can also handle vectors and maybe some other kinds of
>        structures.

Don't we have that under the name `equal`?
I mean I understand you intend the above `match` to work without memory
allocation, but it seems that it's just an optimization.
Or am I missing something?

> (match-set PATTERN VALUE)
>        This is a macro.
>        PATTERN is a backquote form which specifies which parts of
>        VALUE to match and parts to extract and store.  For instance
>        (match-set `(+ ,y ,z) (get-complex-list))
>        would decompose the result of (get-complex-list), verify the car,
>        and set y and z.
>
>        PATTERN will not be evaluated, just used as guidance when the
>        `match-set' form is macroexpanded, producing code like this:

(defalias 'match-set #'pcase-setq)  🙂

> (match-bind PATTERN VALUE BODY...)
>        Much like `match-set', except that instead of setting the
>        variables found in PATTERN, it let-binds them and runs BODY
>        with those bindings.

This one is not a mere `defalias`:

    (defmacro match-bind (pattern value &rest body)
      `(pcase-let ((,pattern ,value)) ,@body))

There's a tradeoff here, indeed: sometimes I find the added ((...))
of `pcase-let` rather annoying, but other times the fact that it's
a superset of `let` means I get to mix it with normal bindings without
increasing the nesting depth, which improves readability.


        Stefn




^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: Instead of pcase
  2023-11-25  4:34     ` Stefan Monnier via Emacs development discussions.
@ 2023-11-25  8:53       ` Eli Zaretskii
  0 siblings, 0 replies; 342+ messages in thread
From: Eli Zaretskii @ 2023-11-25  8:53 UTC (permalink / raw)
  To: Stefan Monnier; +Cc: emacs-devel

> Date: Fri, 24 Nov 2023 23:34:24 -0500
> From:  Stefan Monnier via "Emacs development discussions." <emacs-devel@gnu.org>
> 
> > (let ((exp (if t '(foo . "str") '(bar . 7))))
> >   (cl-case (car exp)
> >     (foo
> >      (when-let ((d (cdr exp)))
> >        (concat "str" val)))
> >     (bar
> >      (when-let ((d (cdr exp)))
> >        (1+ val)))))
> 
> AKA
> 
>     (let ((exp (if t '(foo . "str") '(bar . 7))))
>       (case (car exp)
>         ('foo
>          (when-let ((d (cdr exp)))
>            (concat "str" val)))
>         ('bar
>          (when-let ((d (cdr exp)))
>            (1+ val)))))
> 
> Funnily enough this quoting of the values against which we want to match
> is so natural for coders not familiar with `cl-case` that we went
> through some efforts to try and detect their mis-use.
> 
> So at least for some coders, in the above case, the `pcase` syntax is the
> more natural one :-)

And 'cond' is more natural yet (in these simple cases).  Basically,
all that pcase saves us there is the call to 'eq'.



^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: combining cond and let, to replace pcase.
  2023-11-23  7:02       ` Tomas Hlavaty
@ 2023-11-26  3:14         ` Richard Stallman
  2023-11-27 17:07           ` Tomas Hlavaty
  0 siblings, 1 reply; 342+ messages in thread
From: Richard Stallman @ 2023-11-26  3:14 UTC (permalink / raw)
  To: Tomas Hlavaty; +Cc: emacs-devel

[[[ To any NSA and FBI agents reading my email: please consider    ]]]
[[[ whether defending the US Constitution against all enemies,     ]]]
[[[ foreign or domestic, requires you to follow Snowden's example. ]]]

  > >        ;; Same as a clause in `cond',
  > >        (CONDITION
  > >         do-this-if-CONDITION-then-exit...)
  > >
  > >        ;; Variables to bind, as in let
  > >        (:bind (x foobar) y z (foo 5) a)
  > >        ;; Bindings continue in effect.

  > This seems nicer:

  > (if CONDITION
  >     do-this-if-CONDITION-then-exit...
  >     (let ((x foobar) y z (foo 5) a)
  >       ...))

That is what you can do now with `if' and `let', but many levels of
nexting get to be inconvenient and hard to read.  That is one of the
practical conveniences of _using_ `pcase'.  I think a replacement for
`pcase' should offer the same advantage.

  > It looks like everybody is trying to design a "do it all super-macro"

If that refers to the approach of `pcase', in which there are dozens
of different features one must learn, then `cond*' represents turning
away from that approach.  `cond*' has just four features, two of which
are modified from `cond'.

That's why `cond*' will impose less burden of language complexity than
`pcase'.

-- 
Dr Richard Stallman (https://stallman.org)
Chief GNUisance of the GNU Project (https://gnu.org)
Founder, Free Software Foundation (https://fsf.org)
Internet Hall-of-Famer (https://internethalloffame.org)





^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: combining cond and let, to replace pcase.
  2023-11-23  8:58       ` Manuel Giraud via Emacs development discussions.
@ 2023-11-26  3:14         ` Richard Stallman
  0 siblings, 0 replies; 342+ messages in thread
From: Richard Stallman @ 2023-11-26  3:14 UTC (permalink / raw)
  To: Manuel Giraud; +Cc: emacs-devel

[[[ To any NSA and FBI agents reading my email: please consider    ]]]
[[[ whether defending the US Constitution against all enemies,     ]]]
[[[ foreign or domestic, requires you to follow Snowden's example. ]]]

  > Only gut feelings here, but fall thru with bindings by default and
  > multiple t may surprise users and lead to not simple to debug code.

It would be a trivial change to replace t with some keyword, for that
functionality.  Would it actually be better?  What do other s think?

Here's a more uniform version, in which each clause
exits if it contains more than one element (after the possible keyword),
and falls through otherwise.  This makes it unnecessary to redefine
what t means as a condition -- that can be written another way (see below).

(cond* 
       ;; Same as a clause in `cond',
       (CONDITION
        DO-THIS-IF-TRUE-THEN-EXIT...)

       ;; Execute FORM and ignore its value.
       (FORM)

       ;; Variables to bind, as in let
       (:bind ((x foobar) y z (foo 5) a))
       ;; Bindings continue in effect.

       ;; Extracts substructure and binds variables around the rest
       ;; of the cond*.
       (:match (`(expt ,foo ,bar) x)
        DO-THIS-IF-IT-MATCHED-THEN-EXIT...)
       ;; Bindings continue in effect.

       ;; Like above but always falls thru to next clause.
       (:match (`(expt ,foo ,bar) x))
       ;; Bindings continue in effect.
       )



To execute several expressions and not exit, use this:

       ((progn DO-THIS-UNCONDITIONALLY-AND-DONT-STOP...)


-- 
Dr Richard Stallman (https://stallman.org)
Chief GNUisance of the GNU Project (https://gnu.org)
Founder, Free Software Foundation (https://fsf.org)
Internet Hall-of-Famer (https://internethalloffame.org)





^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: Instead of pcase
  2023-11-16  7:37 ` Philip Kaludercic
  2023-11-16 17:18   ` T.V Raman
@ 2023-11-26  3:17   ` Richard Stallman
  1 sibling, 0 replies; 342+ messages in thread
From: Richard Stallman @ 2023-11-26  3:17 UTC (permalink / raw)
  To: Philip Kaludercic; +Cc: emacs-devel

[[[ To any NSA and FBI agents reading my email: please consider    ]]]
[[[ whether defending the US Constitution against all enemies,     ]]]
[[[ foreign or domestic, requires you to follow Snowden's example. ]]]

  >   The question is, if
  > one would restrict pcase to just matching expressions using ` and , like

  >   (pcase sexp ;match various top-level constructs

I am not sure what ";match various top-level constructs" means.

  >     (`(defun ,name ,args ,body) ...)
  >     (`(defvar ,name, ,value) ...)
  >     (`(require ',symbol) ...)
  >     ...)

That part is conceptually simple.

  > would that be simple enough in your opinion?


-- 
Dr Richard Stallman (https://stallman.org)
Chief GNUisance of the GNU Project (https://gnu.org)
Founder, Free Software Foundation (https://fsf.org)
Internet Hall-of-Famer (https://internethalloffame.org)





^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: Instead of pcase
  2023-11-24 17:14                         ` Dmitry Gutov
@ 2023-11-27  3:09                           ` Richard Stallman
  2023-11-27 12:21                             ` Dmitry Gutov
  2023-11-28  2:44                           ` Richard Stallman
  1 sibling, 1 reply; 342+ messages in thread
From: Richard Stallman @ 2023-11-27  3:09 UTC (permalink / raw)
  To: Dmitry Gutov; +Cc: michael_heerdegen, emacs-devel

[[[ To any NSA and FBI agents reading my email: please consider    ]]]
[[[ whether defending the US Constitution against all enemies,     ]]]
[[[ foreign or domestic, requires you to follow Snowden's example. ]]]

  > I suggest you try rewriting the definition of completion-help-at-point 
  > using your alternative construct.

I tried to do this, and it isn't hard to do this by formulating each clause
to use :match.

However, to make the simplest possible result, I need to know
all the kinds of values that RES can have.  For instance, at this point,

      (`(,hookfun . ,_)
       ;; The hook function already performed completion :-(
       ;; Not much we can do at this point.
       (message "%s already performed completion!" hookfun)
       nil)

what are the possible values of RES that will NOT match that pattern?

-- 
Dr Richard Stallman (https://stallman.org)
Chief GNUisance of the GNU Project (https://gnu.org)
Founder, Free Software Foundation (https://fsf.org)
Internet Hall-of-Famer (https://internethalloffame.org)





^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: combining cond and let, to replace pcase.
  2023-11-25  5:11       ` Stefan Monnier via Emacs development discussions.
  2023-11-27  3:11         ` Richard Stallman
@ 2023-11-27  3:11         ` Richard Stallman
  2023-11-27 18:13           ` Manuel Giraud via Emacs development discussions.
  1 sibling, 1 reply; 342+ messages in thread
From: Richard Stallman @ 2023-11-27  3:11 UTC (permalink / raw)
  To: Stefan Monnier; +Cc: emacs-devel

[[[ To any NSA and FBI agents reading my email: please consider    ]]]
[[[ whether defending the US Constitution against all enemies,     ]]]
[[[ foreign or domestic, requires you to follow Snowden's example. ]]]

  > >        ;; Extracts substructure and binds variables around the rest
  > >        ;; of the cond*.
  > >        (:match (`(expt ,foo ,bar) x)
  > >         do-this-if-it-matched-then-exit...)
  > >        ;; Bindings continue in effect.

  > Which bindings?  Presumably when we continue the match failed, so `foo`
  > and `bar` don't have any meaningful value to take, AFAICT.

That is a good question.

I've concluded that, for this form of the clause, which will exit if
it executes the body of the clause, the bindings should be made only
for that clause.

  > >        ;; Like above but always falls thru to next clause.
  > >        (:match (`(expt ,foo ,bar) x))
  > >        ;; Bindings continue in effect.

  > What happens if `(car x)` is not equal to `expt` or if `x` is a string?

This form of clause should bind the variables unconditionally.  If
matching provides a value to give a certain variable, the variable
should get that value.  Otherwise it should be bound to nil.

This way, which variablss are bound at any point will not depend on
the valus of the data.

-- 
Dr Richard Stallman (https://stallman.org)
Chief GNUisance of the GNU Project (https://gnu.org)
Founder, Free Software Foundation (https://fsf.org)
Internet Hall-of-Famer (https://internethalloffame.org)





^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: combining cond and let, to replace pcase.
  2023-11-25  5:11       ` Stefan Monnier via Emacs development discussions.
@ 2023-11-27  3:11         ` Richard Stallman
  2023-11-27  3:11         ` Richard Stallman
  1 sibling, 0 replies; 342+ messages in thread
From: Richard Stallman @ 2023-11-27  3:11 UTC (permalink / raw)
  To: Stefan Monnier; +Cc: emacs-devel

[[[ To any NSA and FBI agents reading my email: please consider    ]]]
[[[ whether defending the US Constitution against all enemies,     ]]]
[[[ foreign or domestic, requires you to follow Snowden's example. ]]]

  > (defalias 'match-set #'pcase-setq)

I'm not defining these constructs based on pcase.
I'm defining them to be useful together with cond*.
If one of them resembles a part of pcase, that is a coincidence
even if not entirely surprising.

Maybe we can copy parts of that pcase code with changes, smaller or
larger.  However, the definitions of these constructs will not depend
on pcase.

  > There's a tradeoff here, indeed: sometimes I find the added ((...))
  > of `pcase-let` rather annoying, but other times the fact that it's
  > a superset of `let` means I get to mix it with normal bindings without
  > increasing the nesting depth,

What does that mean, concretely?  I am not sure.  I have (not
coincidentally) little experience with reading code that uses pcase.

-- 
Dr Richard Stallman (https://stallman.org)
Chief GNUisance of the GNU Project (https://gnu.org)
Founder, Free Software Foundation (https://fsf.org)
Internet Hall-of-Famer (https://internethalloffame.org)





^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: Instead of pcase
  2023-11-25  4:23                     ` Stefan Monnier via Emacs development discussions.
@ 2023-11-27  3:12                       ` Richard Stallman
  0 siblings, 0 replies; 342+ messages in thread
From: Richard Stallman @ 2023-11-27  3:12 UTC (permalink / raw)
  To: Stefan Monnier; +Cc: emacs-devel

[[[ To any NSA and FBI agents reading my email: please consider    ]]]
[[[ whether defending the US Constitution against all enemies,     ]]]
[[[ foreign or domestic, requires you to follow Snowden's example. ]]]

  > I have toyed with the idea of providing the guards separately from the
  > patterns, but not enough to find something satisfactory.

Would you like to try writing such cases for `cond*', and report on
cases that are natural or not?

-- 
Dr Richard Stallman (https://stallman.org)
Chief GNUisance of the GNU Project (https://gnu.org)
Founder, Free Software Foundation (https://fsf.org)
Internet Hall-of-Famer (https://internethalloffame.org)





^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: Instead of pcase
  2023-11-25  4:15                 ` Stefan Monnier
@ 2023-11-27  3:12                   ` Richard Stallman
  2023-11-30 18:06                     ` Michael Heerdegen
  0 siblings, 1 reply; 342+ messages in thread
From: Richard Stallman @ 2023-11-27  3:12 UTC (permalink / raw)
  To: Stefan Monnier; +Cc: emacs-devel, monnier

[[[ To any NSA and FBI agents reading my email: please consider    ]]]
[[[ whether defending the US Constitution against all enemies,     ]]]
[[[ foreign or domestic, requires you to follow Snowden's example. ]]]

  > Interesting.  `pcase` is a macro, so it does not see the above
  > characters, it only sees the resulting Sexp returned by the Lisp reader,
  > and as you may remember, the reader returns *exactly* the same Sexp
  > for the above two lines of text.

You're right, but I didn't see that, because I was thinking of it as
part of a pcase construct and assumed it would produce some unknown
code to do the matching.  I didn't see that pcase and backwuote itself
would not notice the difference.

For me, pcase shines a cone of mystery.

-- 
Dr Richard Stallman (https://stallman.org)
Chief GNUisance of the GNU Project (https://gnu.org)
Founder, Free Software Foundation (https://fsf.org)
Internet Hall-of-Famer (https://internethalloffame.org)





^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: Instead of pcase
  2023-11-24 18:14                         ` Michael Heerdegen
  2023-11-24 18:35                           ` Dmitry Gutov
@ 2023-11-27  3:14                           ` Richard Stallman
  2023-11-28  2:46                             ` Richard Stallman
  2023-12-10 15:14                             ` Richard Stallman
  1 sibling, 2 replies; 342+ messages in thread
From: Richard Stallman @ 2023-11-27  3:14 UTC (permalink / raw)
  To: Michael Heerdegen; +Cc: emacs-devel

[[[ To any NSA and FBI agents reading my email: please consider    ]]]
[[[ whether defending the US Constitution against all enemies,     ]]]
[[[ foreign or domestic, requires you to follow Snowden's example. ]]]

  > I collected some more or less random examples that combine several
  > `pcase' features and are not too long:

  >   ffap-other-window
  >   menu-bar-item-at-x
  >   completion-at-point
  >   byte-optimize-funcall
  >   byte-optimize-letX
  >   cl-typep

Thanks.  I will look at one or two of them tomorrow.

  > I would suggest to look at some more complex cases where several `pcase'
  > features appear combined.

Would you like to pick one of them and see what rewriting it with cond*
would look like?  

-- 
Dr Richard Stallman (https://stallman.org)
Chief GNUisance of the GNU Project (https://gnu.org)
Founder, Free Software Foundation (https://fsf.org)
Internet Hall-of-Famer (https://internethalloffame.org)





^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: Instead of pcase
  2023-11-27  3:09                           ` Richard Stallman
@ 2023-11-27 12:21                             ` Dmitry Gutov
  2023-11-29  3:42                               ` Richard Stallman
  0 siblings, 1 reply; 342+ messages in thread
From: Dmitry Gutov @ 2023-11-27 12:21 UTC (permalink / raw)
  To: rms; +Cc: michael_heerdegen, emacs-devel

On 27/11/2023 05:09, Richard Stallman wrote:
> [[[ To any NSA and FBI agents reading my email: please consider    ]]]
> [[[ whether defending the US Constitution against all enemies,     ]]]
> [[[ foreign or domestic, requires you to follow Snowden's example. ]]]
> 
>    > I suggest you try rewriting the definition of completion-help-at-point
>    > using your alternative construct.
> 
> I tried to do this, and it isn't hard to do this by formulating each clause
> to use :match.

I didn't think it would be difficult. But then one would compare the 
solutions.

> However, to make the simplest possible result, I need to know
> all the kinds of values that RES can have.  For instance, at this point,
> 
>        (`(,hookfun . ,_)
>         ;; The hook function already performed completion :-(
>         ;; Not much we can do at this point.
>         (message "%s already performed completion!" hookfun)
>         nil)
> 
> what are the possible values of RES that will NOT match that pattern?

Since "_" means "anything", the pcase form does enumerate all possible 
options (anything else would be a bug in the code producing res).



^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: combining cond and let, to replace pcase.
  2023-11-26  3:14         ` Richard Stallman
@ 2023-11-27 17:07           ` Tomas Hlavaty
  2023-11-27 17:59             ` Yuri Khan
  0 siblings, 1 reply; 342+ messages in thread
From: Tomas Hlavaty @ 2023-11-27 17:07 UTC (permalink / raw)
  To: rms; +Cc: emacs-devel

On Sat 25 Nov 2023 at 22:14, Richard Stallman <rms@gnu.org> wrote:
>   > >        ;; Same as a clause in `cond',
>   > >        (CONDITION
>   > >         do-this-if-CONDITION-then-exit...)
>   > >
>   > >        ;; Variables to bind, as in let
>   > >        (:bind (x foobar) y z (foo 5) a)
>   > >        ;; Bindings continue in effect.
>
>   > This seems nicer:
>
>   > (if CONDITION
>   >     do-this-if-CONDITION-then-exit...
>   >     (let ((x foobar) y z (foo 5) a)
>   >       ...))
>
> That is what you can do now with `if' and `let', but many levels of
> nexting get to be inconvenient and hard to read.  That is one of the
> practical conveniences of _using_ `pcase'.  I think a replacement for
> `pcase' should offer the same advantage.

if you are after less nesting, cond or or can already do that:

   (cond
     ;; Same as a clause in `cond',
     (CONDITION
      do-this-if-CONDITION-then-exit...)
     ;; Variables to bind, as in let
     ((let ((x foobar) y z (foo 5) a)
       ;; Bindings continue in effect.
       ...))
     ...)

even better:

   (or
     ;; Same as a clause in `cond',
     (when CONDITION
       do-this-if-CONDITION-then-exit...)
     ;; Variables to bind, as in let
     (let ((x foobar) y z (foo 5) a)
       ;; Bindings continue in effect.
       ...)
     ...)

no need for :bind which seems like superficial syntax that requires
extra cond* macro definition with weird rules.

>   > It looks like everybody is trying to design a "do it all super-macro"
>
> If that refers to the approach of `pcase', in which there are dozens
> of different features one must learn, then `cond*' represents turning
> away from that approach.  `cond*' has just four features, two of which
> are modified from `cond'.
>
> That's why `cond*' will impose less burden of language complexity than
> `pcase'.

or, when, let are even simpler and the example with or is even more
readable.  I do not see what cond* brings.  It seems that existing forms
cover the control flow part well enough.  What should be the focus is
the destructuring part, like cl-destructuring-bind or your match,
match-set, match-bind or the matching part of pcase.

Btw there is even a kind of user-configurable version of the or macro, a
kind of pluggable-or called run-hook-with-args-until-success which is
like the or macro but with cases as functions in a list.  This could
allow for use-extensible variant, if the destructuring part was separate
and reuseable.



^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: combining cond and let, to replace pcase.
  2023-11-27 17:07           ` Tomas Hlavaty
@ 2023-11-27 17:59             ` Yuri Khan
  2023-11-28 14:25               ` Tomas Hlavaty
  0 siblings, 1 reply; 342+ messages in thread
From: Yuri Khan @ 2023-11-27 17:59 UTC (permalink / raw)
  To: Tomas Hlavaty; +Cc: rms, emacs-devel

On Tue, 28 Nov 2023 at 00:10, Tomas Hlavaty <tom@logand.com> wrote:

> even better:>
>    (or
>      ;; Same as a clause in `cond',
>      (when CONDITION
>        do-this-if-CONDITION-then-exit...)
>      ;; Variables to bind, as in let
>      (let ((x foobar) y z (foo 5) a)
>        ;; Bindings continue in effect.
>        ...)
>      ...)

This reminds me of the times before Python 2.x had a ternary operator
‘X if CONDITION else Y’. Some FAQs said “you can use this trick:
‘CONDITION and X or Y’”, with a small print (sometimes skipped) “as
long as you guarantee that X evaluates to a truthy value”.

This is very error-prone. Novices can and will get bitten by this.

* ‘or’ evaluates its arguments in turn until one of them evaluates to non-nil.
* ‘when’ and ‘let’ evaluate to the last body form if any, or nil if none.

So, for the intended effect of exiting the ‘or’ when a branch is
taken, one has to make sure to terminate that branch with a truthy
expression:

    (or
      (when CONDITION
        do-this-possibly-returning-nil
        :break)
      (let (BINDINGS)
        do-something-else-possibly-returning-nil
        :break)
      …more branches…)

Also, a ‘cond’ or a ‘pcase’ form will return the result of the branch
taken, which can be nil. An ‘or’ form will return the result of the
branch taken, as long as it is not nil. A branch that returns nil will
result in evaluation of the next branch.



^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: combining cond and let, to replace pcase.
  2023-11-27  3:11         ` Richard Stallman
@ 2023-11-27 18:13           ` Manuel Giraud via Emacs development discussions.
  2023-11-27 18:49             ` Yuri Khan
  2023-11-29  3:40             ` Richard Stallman
  0 siblings, 2 replies; 342+ messages in thread
From: Manuel Giraud via Emacs development discussions. @ 2023-11-27 18:13 UTC (permalink / raw)
  To: Richard Stallman; +Cc: Stefan Monnier, emacs-devel

Richard Stallman <rms@gnu.org> writes:

[...]

>   > >        ;; Like above but always falls thru to next clause.
>   > >        (:match (`(expt ,foo ,bar) x))
>   > >        ;; Bindings continue in effect.
>
>   > What happens if `(car x)` is not equal to `expt` or if `x` is a string?
>
> This form of clause should bind the variables unconditionally.  If
> matching provides a value to give a certain variable, the variable
> should get that value.  Otherwise it should be bound to nil.

So these form of :match clause would bind variables even though it did
not match?  That seems counter-intuitive to me.
-- 
Manuel Giraud



^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: combining cond and let, to replace pcase.
  2023-11-27 18:13           ` Manuel Giraud via Emacs development discussions.
@ 2023-11-27 18:49             ` Yuri Khan
  2023-11-27 23:12               ` Stefan Monnier
  2023-11-29  3:41               ` Richard Stallman
  2023-11-29  3:40             ` Richard Stallman
  1 sibling, 2 replies; 342+ messages in thread
From: Yuri Khan @ 2023-11-27 18:49 UTC (permalink / raw)
  To: Manuel Giraud; +Cc: Richard Stallman, Stefan Monnier, emacs-devel

On Tue, 28 Nov 2023 at 01:14, Manuel Giraud via Emacs development
discussions. <emacs-devel@gnu.org> wrote:
>
> Richard Stallman <rms@gnu.org> writes:
>
> [...]
>
> >   > >        ;; Like above but always falls thru to next clause.
> >   > >        (:match (`(expt ,foo ,bar) x))
> >   > >        ;; Bindings continue in effect.
> >
> >   > What happens if `(car x)` is not equal to `expt` or if `x` is a string?
> >
> > This form of clause should bind the variables unconditionally.  If
> > matching provides a value to give a certain variable, the variable
> > should get that value.  Otherwise it should be bound to nil.
>
> So these form of :match clause would bind variables even though it did
> not match?  That seems counter-intuitive to me.

Not only that, it’s just plain wrong.

    (pcase 42
      (`(,x . ,y) (format "%s:%s" x y))
      (_ "not a cons cell"))
    → not a cons cell

If I understand Richard correctly, the corresponding :match will
unconditionally attempt to bind x to (car 42) and y to (cdr 42), which
results in a run-time error.

The correct pattern matching behavior is to first check that the
expression being matched is indeed a cons, and only if so, destructure
it into its car and cdr.

Similarly, attempting to match a two-element list (expt 2) with a
three-element pattern (expt ,x ,y) is nonsensical and it’s not helpful
to bind y to (caddr '(expt 2)) == nil. Same if the list and pattern
have the same length but literal elements do not match, e.g. '(+ 42
73) against '(expt ,base ,exponent).



^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: combining cond and let, to replace pcase.
  2023-11-27 18:49             ` Yuri Khan
@ 2023-11-27 23:12               ` Stefan Monnier
  2023-11-29  3:41               ` Richard Stallman
  1 sibling, 0 replies; 342+ messages in thread
From: Stefan Monnier @ 2023-11-27 23:12 UTC (permalink / raw)
  To: Yuri Khan; +Cc: Manuel Giraud, Richard Stallman, emacs-devel

>> >   > >        ;; Like above but always falls thru to next clause.
>> >   > >        (:match (`(expt ,foo ,bar) x))
>> >   > >        ;; Bindings continue in effect.
>> >
>> >   > What happens if `(car x)` is not equal to `expt` or if `x` is a string?
>> >
>> > This form of clause should bind the variables unconditionally.  If
>> > matching provides a value to give a certain variable, the variable
>> > should get that value.  Otherwise it should be bound to nil.
>>
>> So these form of :match clause would bind variables even though it did
>> not match?  That seems counter-intuitive to me.
>
> Not only that, it’s just plain wrong.
>
>     (pcase 42
>       (`(,x . ,y) (format "%s:%s" x y))
>       (_ "not a cons cell"))
>     → not a cons cell

But those above `:match` is not a test, it's a destructuring operation
only, so it's more like

    (pcase-let ((`(,x . ,y) 42))
      ...)

> If I understand Richard correctly, the corresponding :match will
> unconditionally attempt to bind x to (car 42) and y to (cdr 42), which
> results in a run-time error.

`pcase` uses `car-safe` and `cdr-safe` tho it was not to avoid such
errors (it was to allow those operations to be optimized away if
the result is not used).

`:match` could similarly use `car-safe` and `cdr-safe`.


        Stefan




^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: Instead of pcase
  2023-11-24 17:29                 ` Lynn Winebarger
@ 2023-11-28  2:44                   ` Richard Stallman
  2023-11-30 19:14                     ` Lynn Winebarger
  0 siblings, 1 reply; 342+ messages in thread
From: Richard Stallman @ 2023-11-28  2:44 UTC (permalink / raw)
  To: Lynn Winebarger; +Cc: dmitry, philipk, emacs-devel

[[[ To any NSA and FBI agents reading my email: please consider    ]]]
[[[ whether defending the US Constitution against all enemies,     ]]]
[[[ foreign or domestic, requires you to follow Snowden's example. ]]]

  > > In particular, what is the reason for the period and inner
  > > parenthsses?  Why doesn't the code say this?


  > > >          > (`(,hookfun ,start ,end ,collection . ,plist)

  > I would think the author is simply emphasizing that [perse is] parsing an
  > entity in an association list for which hookfun is a key.

You may well be right about per intensions, and it is possible that a
person who already fully understands what this code is doing would
have realized that immediately.

But a person who is just starting to look at this code, and reads that
function first, is likely to be impeded in starting to reach that sort
of understanding.

-- 
Dr Richard Stallman (https://stallman.org)
Chief GNUisance of the GNU Project (https://gnu.org)
Founder, Free Software Foundation (https://fsf.org)
Internet Hall-of-Famer (https://internethalloffame.org)





^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: Instead of pcase
  2023-11-24 17:14                         ` Dmitry Gutov
  2023-11-27  3:09                           ` Richard Stallman
@ 2023-11-28  2:44                           ` Richard Stallman
  2023-11-28 12:39                             ` Dmitry Gutov
  1 sibling, 1 reply; 342+ messages in thread
From: Richard Stallman @ 2023-11-28  2:44 UTC (permalink / raw)
  To: Dmitry Gutov; +Cc: michael_heerdegen, emacs-devel

[[[ To any NSA and FBI agents reading my email: please consider    ]]]
[[[ whether defending the US Constitution against all enemies,     ]]]
[[[ foreign or domestic, requires you to follow Snowden's example. ]]]

  > I suggest you try rewriting the definition of completion-help-at-point 
  > using your alternative construct.

I did that, and found that translating that particular pcase to use
cond* resulted in something about equally complex.  But I recognized
some changess to make in cond* as a result.  Those changes are in the
newer version I sent out during the weekend.

Thanks.

-- 
Dr Richard Stallman (https://stallman.org)
Chief GNUisance of the GNU Project (https://gnu.org)
Founder, Free Software Foundation (https://fsf.org)
Internet Hall-of-Famer (https://internethalloffame.org)





^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: Instead of pcase
  2023-11-27  3:14                           ` Richard Stallman
@ 2023-11-28  2:46                             ` Richard Stallman
  2023-11-28  6:35                               ` Nikita Domnitskii
  2023-12-10 15:14                             ` Richard Stallman
  1 sibling, 1 reply; 342+ messages in thread
From: Richard Stallman @ 2023-11-28  2:46 UTC (permalink / raw)
  To: michael_heerdegen; +Cc: emacs-devel

[[[ To any NSA and FBI agents reading my email: please consider    ]]]
[[[ whether defending the US Constitution against all enemies,     ]]]
[[[ foreign or domestic, requires you to follow Snowden's example. ]]]

    (defun ffap-other-window (filename)
      "Like `ffap', but put buffer in another window.
    Only intended for interactive use."
      (interactive (list (ffap-prompter nil " other window")))
      (pcase (save-window-excursion (find-file-at-point filename))
        ((or (and (pred bufferp) b) `(,(and (pred bufferp) b) . ,_))
         (switch-to-buffer-other-window b))))

I had to struggle to understand that use of pcase.
Once I understood it, I found these ways to rewrite it.

  (cond* (:bind b1 (b (save-window-excursion (find-file-at-point filename))))
         ((bufferp b) (setq b1 b))
         ((bufferp (car-safe b)) (setq b1 (car-safe b))))
  (if b1 (switch-to-buffer-other-window b)))

  (cond* (:bind b1 (b (save-window-excursion (find-file-at-point filename))))
         ((bufferp b) (switch-to-buffer-other-window b))
         ((bufferp (car-safe b)) (switch-to-buffer-other-window (car-safe b)))))

I concluded it was essirable to give the macro `match-set' an optional third
argument, which is an expression that does the job of what pcase calls
a "guard".  It is an ordinary Lisp expression.

Also, to make `match-set' return t if it succeeded in matching.

Thus I came up with this.

  (let ((b (save-window-excursion (find-file-at-point filename))) b1)
    (if (or (match-set b1 b (bufferp b1))
            (match-set b1 (car-safe b) (bufferp b1)))
        (switch-to-buffer-other-window b1)))

-- 
Dr Richard Stallman (https://stallman.org)
Chief GNUisance of the GNU Project (https://gnu.org)
Founder, Free Software Foundation (https://fsf.org)
Internet Hall-of-Famer (https://internethalloffame.org)





^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: Instead of pcase
  2023-11-28  2:46                             ` Richard Stallman
@ 2023-11-28  6:35                               ` Nikita Domnitskii
  2023-11-30  3:37                                 ` Richard Stallman
  2023-12-02 21:37                                 ` Lynn Winebarger
  0 siblings, 2 replies; 342+ messages in thread
From: Nikita Domnitskii @ 2023-11-28  6:35 UTC (permalink / raw)
  To: rms, michael_heerdegen; +Cc: emacs-devel

Richard Stallman <rms@gnu.org> writes:

>   (cond* (:bind b1 (b (save-window-excursion (find-file-at-point filename))))
>          ((bufferp b) (setq b1 b))
>          ((bufferp (car-safe b)) (setq b1 (car-safe b))))
>   (if b1 (switch-to-buffer-other-window b)))
>
>   (cond* (:bind b1 (b (save-window-excursion (find-file-at-point filename))))
>          ((bufferp b) (switch-to-buffer-other-window b))
>          ((bufferp (car-safe b)) (switch-to-buffer-other-window (car-safe b)))))
>
>   (let ((b (save-window-excursion (find-file-at-point filename))) b1)
>     (if (or (match-set b1 b (bufferp b1))
>             (match-set b1 (car-safe b) (bufferp b1)))
>         (switch-to-buffer-other-window b1)))

To be honest all variants look less expressive than original
pcase.

Maybe instead of trying to implement cond* we should look into impoving
pcase patterns? As a starting point I suggest Racket pattern matching
implementation (which in my opinion is fairly readable):
https://docs.racket-lang.org/reference/match.html

-- 
Best Regards,
Nikita Domnitskii



^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: Instead of pcase
  2023-11-28  2:44                           ` Richard Stallman
@ 2023-11-28 12:39                             ` Dmitry Gutov
  2023-11-30  3:37                               ` Richard Stallman
  0 siblings, 1 reply; 342+ messages in thread
From: Dmitry Gutov @ 2023-11-28 12:39 UTC (permalink / raw)
  To: rms; +Cc: michael_heerdegen, emacs-devel

On 28/11/2023 04:44, Richard Stallman wrote:
>    > I suggest you try rewriting the definition of completion-help-at-point
>    > using your alternative construct.
> 
> I did that, and found that translating that particular pcase to use
> cond* resulted in something about equally complex.

I guess that's the point I wanted to underscore: that those pcase uses 
are more-or-less optimal in terms of complexity (for its ultimate 
goals), that in most cases it comes from the problem domain rather than 
from the solution.

And I'm guessing your solutions were more verbose, if anything.

> But I recognized
> some changess to make in cond* as a result.  Those changes are in the
> newer version I sent out during the weekend.

Happy to help. Though note that simply adding a new way to do the same 
thing that's not better by a sufficiently large margin, usually leads to 
"now we have N+1 standards".



^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: combining cond and let, to replace pcase.
  2023-11-27 17:59             ` Yuri Khan
@ 2023-11-28 14:25               ` Tomas Hlavaty
  0 siblings, 0 replies; 342+ messages in thread
From: Tomas Hlavaty @ 2023-11-28 14:25 UTC (permalink / raw)
  To: Yuri Khan; +Cc: rms, emacs-devel

On Tue 28 Nov 2023 at 00:59, Yuri Khan <yuri.v.khan@gmail.com> wrote:
> So, for the intended effect of exiting the ‘or’ when a branch is
> taken, one has to make sure to terminate that branch with a truthy
> expression:
>
>     (or
>       (when CONDITION
>         do-this-possibly-returning-nil
>         :break)
>       (let (BINDINGS)
>         do-something-else-possibly-returning-nil
>         :break)
>       …more branches…)
>
> Also, a ‘cond’ or a ‘pcase’ form will return the result of the branch
> taken, which can be nil.  An ‘or’ form will return the result of the
> branch taken, as long as it is not nil. A branch that returns nil will
> result in evaluation of the next branch.

same issue with cond:

(cond
  ((let (bindings)
     'do-something-else-possibly-returning-nil
     nil))
  (t :default))
=> :default

(cond
  ((let (bindings)
     'do-something-else-possibly-returning-nil
     :break))
  (t :default))
=> :break



^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: combining cond and let, to replace pcase.
  2023-11-25  4:45         ` Stefan Monnier via Emacs development discussions.
@ 2023-11-28 15:31           ` João Távora
  2023-11-28 15:55             ` Stefan Monnier
  0 siblings, 1 reply; 342+ messages in thread
From: João Távora @ 2023-11-28 15:31 UTC (permalink / raw)
  To: Stefan Monnier; +Cc: emacs-devel

On Sat, Nov 25, 2023 at 4:45 AM Stefan Monnier via Emacs development
discussions. <emacs-devel@gnu.org> wrote:
>
> > that is why cl-loop and maybe pcase are "ugly"
> > one heuristic could be if autodoc can display something useful
>
> I suspect it would be difficult to do for `cl-loop` (would require heavy
> hacking on `cl-loop` itself),

Would it?  Isn't this more or less the same information that Edebug
already has for stepping through it?

Also, has someone also posted the obligatory https://xkcd.com/927/
here?



^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: combining cond and let, to replace pcase.
  2023-11-28 15:31           ` João Távora
@ 2023-11-28 15:55             ` Stefan Monnier
  0 siblings, 0 replies; 342+ messages in thread
From: Stefan Monnier @ 2023-11-28 15:55 UTC (permalink / raw)
  To: João Távora; +Cc: emacs-devel

>> > that is why cl-loop and maybe pcase are "ugly"
>> > one heuristic could be if autodoc can display something useful
>>
>> I suspect it would be difficult to do for `cl-loop` (would require heavy
>> hacking on `cl-loop` itself),
>
> Would it?  Isn't this more or less the same information that Edebug
> already has for stepping through it?

No, I think Eldoc on subexpressions inside `cl-loop` and `pcase` already
work, the question was rather how to make Eldoc give tips about the
macro's own syntax, e.g. when you're inside a `pred` or a `guard`
display things like

    (guard BOOLEXP)
or
    (pred FUN)

and when you're after an `in` on `cl-loop` maybe something like

    PATTERN in LIST

This info is not included in the Edebug specs :-(
But you're right that maybe we could do that without too much extra work
by adding that info to the Edebug spec.


        Stefan




^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: combining cond and let, to replace pcase.
  2023-11-27 18:13           ` Manuel Giraud via Emacs development discussions.
  2023-11-27 18:49             ` Yuri Khan
@ 2023-11-29  3:40             ` Richard Stallman
  1 sibling, 0 replies; 342+ messages in thread
From: Richard Stallman @ 2023-11-29  3:40 UTC (permalink / raw)
  To: Manuel Giraud; +Cc: emacs-devel

[[[ To any NSA and FBI agents reading my email: please consider    ]]]
[[[ whether defending the US Constitution against all enemies,     ]]]
[[[ foreign or domestic, requires you to follow Snowden's example. ]]]

  > > This form of clause should bind the variables unconditionally.  If
  > > matching provides a value to give a certain variable, the variable
  > > should get that value.  Otherwise it should be bound to nil.

  > So these form of :match clause would bind variables even though it did
  > not match?  That seems counter-intuitive to me.

Since it makes the bindings unconditionally, it has to make the same
bindings whether matching fully succeeds or not.  I don't see any other
alternative -- what could there be?

-- 
Dr Richard Stallman (https://stallman.org)
Chief GNUisance of the GNU Project (https://gnu.org)
Founder, Free Software Foundation (https://fsf.org)
Internet Hall-of-Famer (https://internethalloffame.org)





^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: combining cond and let, to replace pcase.
  2023-11-27 18:49             ` Yuri Khan
  2023-11-27 23:12               ` Stefan Monnier
@ 2023-11-29  3:41               ` Richard Stallman
  1 sibling, 0 replies; 342+ messages in thread
From: Richard Stallman @ 2023-11-29  3:41 UTC (permalink / raw)
  To: Yuri Khan; +Cc: emacs-devel

[[[ To any NSA and FBI agents reading my email: please consider    ]]]
[[[ whether defending the US Constitution against all enemies,     ]]]
[[[ foreign or domestic, requires you to follow Snowden's example. ]]]

  >     (pcase 42
  >       (`(,x . ,y) (format "%s:%s" x y))
  >       (_ "not a cons cell"))
  >     → not a cons cell

  > If I understand Richard correctly,

Alas I think we are miscommunicating.

                                       the corresponding :match will
  > unconditionally attempt to bind x to (car 42) and y to (cdr 42), which
  > results in a run-time error.

pcase has one kind of matching clause.
cond* has two kinds.

It is possible that this distinction is not clear enough in the text I
posted.

In this version, each clause exits if it contains more than one
element (after the possible keyword), and falls through
unconditionally if it has only one element (after the possible
keyword).

For the second kind, I think this addresses your concern.

  (cond* 
       ;; Same as a clause in `cond',
       (CONDITION
        DO-THIS-IF-TRUE-THEN-EXIT...)

       ;; Execute FORM and ignore its value.
       (FORM)

       ;; Variables to bind, as in let
       (:bind ((x foobar) y z (foo 5) a))
       ;; Bindings continue in effect.

       ;; Extracts substructure and binds variables around the rest
       ;; of the cond*.
       (:match (`(expt ,foo ,bar) x)
        DO-THIS-IF-IT-MATCHED-THEN-EXIT...)
       ;; Bindings no longer in effect.

       ;; Like above but always falls thru to next clause.
       (:match (`(expt ,foo ,bar) x))
       ;; Bindings continue in effect.
       ;; All the variables mentioned in the pattern
       ;; are bound whether match succeeds or not.
       ;; If a value can be determined from an incomplete match,
       ;; the variable gets that value.

       )

-- 
Dr Richard Stallman (https://stallman.org)
Chief GNUisance of the GNU Project (https://gnu.org)
Founder, Free Software Foundation (https://fsf.org)
Internet Hall-of-Famer (https://internethalloffame.org)





^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: Instead of pcase
  2023-11-27 12:21                             ` Dmitry Gutov
@ 2023-11-29  3:42                               ` Richard Stallman
  2023-11-29 12:56                                 ` Dmitry Gutov
  0 siblings, 1 reply; 342+ messages in thread
From: Richard Stallman @ 2023-11-29  3:42 UTC (permalink / raw)
  To: Dmitry Gutov; +Cc: michael_heerdegen, emacs-devel

[[[ To any NSA and FBI agents reading my email: please consider    ]]]
[[[ whether defending the US Constitution against all enemies,     ]]]
[[[ foreign or domestic, requires you to follow Snowden's example. ]]]

  > > However, to make the simplest possible result, I need to know
  > > all the kinds of values that RES can have.  For instance, at this point,
  > > 
  > >        (`(,hookfun . ,_)
  > >         ;; The hook function already performed completion :-(
  > >         ;; Not much we can do at this point.
  > >         (message "%s already performed completion!" hookfun)
  > >         nil)
  > > 
  > > what are the possible values of RES that will NOT match that pattern?

  > Since "_" means "anything", the pcase form does enumerate all possible 
  > options 

We had a miscommunication.  Your answer tells me what that pcase
clause recognizes, but the question I am asking is a different one.
My question is about what values of RES are _valid_ at that point in
the code.

            (anything else would be a bug in the code producing res).

My question is about the code producing RES.
What are the values it can produce, and what do they mean?

-- 
Dr Richard Stallman (https://stallman.org)
Chief GNUisance of the GNU Project (https://gnu.org)
Founder, Free Software Foundation (https://fsf.org)
Internet Hall-of-Famer (https://internethalloffame.org)





^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: Instead of pcase
  2023-11-29  3:42                               ` Richard Stallman
@ 2023-11-29 12:56                                 ` Dmitry Gutov
  2023-12-01  3:17                                   ` Richard Stallman
  0 siblings, 1 reply; 342+ messages in thread
From: Dmitry Gutov @ 2023-11-29 12:56 UTC (permalink / raw)
  To: rms; +Cc: michael_heerdegen, emacs-devel

On 29/11/2023 05:42, Richard Stallman wrote:
> [[[ To any NSA and FBI agents reading my email: please consider    ]]]
> [[[ whether defending the US Constitution against all enemies,     ]]]
> [[[ foreign or domestic, requires you to follow Snowden's example. ]]]
> 
>    > > However, to make the simplest possible result, I need to know
>    > > all the kinds of values that RES can have.  For instance, at this point,
>    > >
>    > >        (`(,hookfun . ,_)
>    > >         ;; The hook function already performed completion 🙁
>    > >         ;; Not much we can do at this point.
>    > >         (message "%s already performed completion!" hookfun)
>    > >         nil)
>    > >
>    > > what are the possible values of RES that will NOT match that pattern?
> 
>    > Since "_" means "anything", the pcase form does enumerate all possible
>    > options
> 
> We had a miscommunication.  Your answer tells me what that pcase
> clause recognizes, but the question I am asking is a different one.
> My question is about what values of RES are_valid_  at that point in
> the code.
> 
>              (anything else would be a bug in the code producing res).
> 
> My question is about the code producing RES.
> What are the values it can produce, and what do they mean?

I'm not sure it's productive to explain the whole completion mechanism 
here, and which bits are involved in it.

I just wanted you to assume that the existing code does what it should 
do (there exist only those cases that pcase matches, and the ones it 
does not, should not exist), and to try to rewrite it using a different 
syntax.



^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: Instead of pcase
  2023-11-28  6:35                               ` Nikita Domnitskii
@ 2023-11-30  3:37                                 ` Richard Stallman
  2023-12-02 21:37                                 ` Lynn Winebarger
  1 sibling, 0 replies; 342+ messages in thread
From: Richard Stallman @ 2023-11-30  3:37 UTC (permalink / raw)
  To: Nikita Domnitskii; +Cc: michael_heerdegen, emacs-devel

[[[ To any NSA and FBI agents reading my email: please consider    ]]]
[[[ whether defending the US Constitution against all enemies,     ]]]
[[[ foreign or domestic, requires you to follow Snowden's example. ]]]

  > To be honest all variants look less expressive than original
  > pcase.

That is a strange thing to say -- "less expressive".  Can you explain
what "expressive" means to you?  I am not sure whether that concept
is one I think is desirable or perhaps the opposite of desirable.

I suspect you mean they are less terse -- which is the flip side of
the problem I'm planning to correct.

-- 
Dr Richard Stallman (https://stallman.org)
Chief GNUisance of the GNU Project (https://gnu.org)
Founder, Free Software Foundation (https://fsf.org)
Internet Hall-of-Famer (https://internethalloffame.org)





^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: Instead of pcase
  2023-11-28 12:39                             ` Dmitry Gutov
@ 2023-11-30  3:37                               ` Richard Stallman
  2023-12-01  0:18                                 ` Dmitry Gutov
  0 siblings, 1 reply; 342+ messages in thread
From: Richard Stallman @ 2023-11-30  3:37 UTC (permalink / raw)
  To: Dmitry Gutov; +Cc: michael_heerdegen, emacs-devel

[[[ To any NSA and FBI agents reading my email: please consider    ]]]
[[[ whether defending the US Constitution against all enemies,     ]]]
[[[ foreign or domestic, requires you to follow Snowden's example. ]]]

  > I guess that's the point I wanted to underscore: that those pcase uses 
  > are more-or-less optimal in terms of complexity (for its ultimate 
  > goals), that in most cases it comes from the problem domain rather than 
  > from the solution.

I think the way you measure "complexity" is different from the way I
measure it.  I suspect that your measure does not count the complexity
of learning `pcase' -- that it assumes the reader knows that already.

That complexitu is what I am trying to eliminate.

I also think that you measure "complexity" as the opposite of terseness,
so that a couple of uses of `match-set' is in your view "added complexity".
However, terseness is what makes `pcase' more complex.

-- 
Dr Richard Stallman (https://stallman.org)
Chief GNUisance of the GNU Project (https://gnu.org)
Founder, Free Software Foundation (https://fsf.org)
Internet Hall-of-Famer (https://internethalloffame.org)





^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: Instead of pcase
  2023-11-27  3:12                   ` Richard Stallman
@ 2023-11-30 18:06                     ` Michael Heerdegen
  0 siblings, 0 replies; 342+ messages in thread
From: Michael Heerdegen @ 2023-11-30 18:06 UTC (permalink / raw)
  To: Richard Stallman; +Cc: Stefan Monnier, emacs-devel

Richard Stallman <rms@gnu.org> writes:

> You're right, but I didn't see that, because I was thinking of it as
> part of a pcase construct and assumed it would produce some unknown
> code to do the matching.  I didn't see that pcase and backwuote itself
> would not notice the difference.

Note that `pcase' sees the same sexp produced by the reader, but the
backquote macro is not expanded.  The backquote sexp produced by the
reader is recognized and handled by the `pcase' macro.

Michael.



^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: Instead of pcase
  2023-11-28  2:44                   ` Richard Stallman
@ 2023-11-30 19:14                     ` Lynn Winebarger
  2023-11-30 19:26                       ` Eli Zaretskii
  2023-12-02  3:20                       ` Richard Stallman
  0 siblings, 2 replies; 342+ messages in thread
From: Lynn Winebarger @ 2023-11-30 19:14 UTC (permalink / raw)
  To: Richard Stallman; +Cc: Dmitry Gutov, Philip Kaludercic, emacs-devel

[-- Attachment #1: Type: text/plain, Size: 1072 bytes --]

On Mon, Nov 27, 2023, 9:44 PM Richard Stallman <rms@gnu.org> wrote:

>
>   > > In particular, what is the reason for the period and inner
>   > > parenthsses?  Why doesn't the code say this?
>
>
>   > > >          > (`(,hookfun ,start ,end ,collection . ,plist)
>
>   > I would think the author is simply emphasizing that [perse is] parsing
> an
>   > entity in an association list for which hookfun is a key.
>
> You may well be right about per intensions, and it is possible that a
> person who already fully understands what this code is doing would
> have realized that immediately.
>
> But a person who is just starting to look at this code, and reads that
> function first, is likely to be impeded in starting to reach that sort
> of understanding.
>

I have to respectfully disagree - dotted pair notation is a pretty
fundamental part of LISP syntax, regardless of dialect.  There's no reason
I'm aware of (for human-written code) for a dotted pair to have a list in
the CDR unless the author is emphasizing the pair as being an entry in an
association list.

Lynn

[-- Attachment #2: Type: text/html, Size: 1727 bytes --]

^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: Instead of pcase
  2023-11-30 19:14                     ` Lynn Winebarger
@ 2023-11-30 19:26                       ` Eli Zaretskii
  2023-11-30 20:30                         ` Michael Heerdegen via Emacs development discussions.
  2023-11-30 20:47                         ` João Távora
  2023-12-02  3:20                       ` Richard Stallman
  1 sibling, 2 replies; 342+ messages in thread
From: Eli Zaretskii @ 2023-11-30 19:26 UTC (permalink / raw)
  To: Lynn Winebarger; +Cc: rms, dmitry, philipk, emacs-devel

> From: Lynn Winebarger <owinebar@gmail.com>
> Date: Thu, 30 Nov 2023 14:14:04 -0500
> Cc: Dmitry Gutov <dmitry@gutov.dev>, Philip Kaludercic <philipk@posteo.net>, 
>  emacs-devel <emacs-devel@gnu.org>
> 
>    > > >          > (`(,hookfun ,start ,end ,collection . ,plist)
> 
>    > I would think the author is simply emphasizing that [perse is] parsing an
>    > entity in an association list for which hookfun is a key.
> 
>  You may well be right about per intensions, and it is possible that a
>  person who already fully understands what this code is doing would
>  have realized that immediately.
> 
>  But a person who is just starting to look at this code, and reads that
>  function first, is likely to be impeded in starting to reach that sort
>  of understanding.
> 
> I have to respectfully disagree - dotted pair notation is a pretty fundamental part of LISP syntax,
> regardless of dialect.

I think you are missing the point.  The point is that pcase has so
many semi-magical syntax features that use punctuation characters in
creative ways that every extra punctuation character presents a
puzzle.  Faced with

  (`(,hookfun . ,start ,end))

one immediately asks himself why the period, where in "normal" Lisp
expressions it would be completely redundant?  The fact that it is
there then leaves one wondering whether that period has some "magical"
meaning.

That is the basic problem with every unusual syntax, and the reason
why introducing such DSLs is a disadvantage.



^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: Instead of pcase
  2023-11-30 19:26                       ` Eli Zaretskii
@ 2023-11-30 20:30                         ` Michael Heerdegen via Emacs development discussions.
  2023-12-01  6:24                           ` Eli Zaretskii
  2023-11-30 20:47                         ` João Távora
  1 sibling, 1 reply; 342+ messages in thread
From: Michael Heerdegen via Emacs development discussions. @ 2023-11-30 20:30 UTC (permalink / raw)
  To: emacs-devel

Eli Zaretskii <eliz@gnu.org> writes:

> I think you are missing the point.  The point is that pcase has so
> many semi-magical syntax features that use punctuation characters in
> creative ways that every extra punctuation character presents a
> puzzle.  Faced with
>
>   (`(,hookfun . ,start ,end))

This is not a valid expression and will be rejected by the reader.  Was
it a typo or did you think this would be valid?

> one immediately asks himself why the period, where in "normal" Lisp
> expressions it would be completely redundant?

As had been said: the syntax has been chosen intentionally to underline
that it is important to view the matched thing as a cons instead of a
list.  If people get crazy about the dot, we can choose a different
syntax without the dot.  It is not necessary to use this syntax (unless
the cdr is not a list).  This point is not about `pcase' but about how
the author has chosen to write the pattern.

> The fact that it is there then leaves one wondering whether that
> period has some "magical" meaning.

As an alternative one can have a look at the docstring.  And learn the
read syntax of cons cells in Lisp.  There is not more to wonder about as
there is to wonder about the identity

 (X . (Y ...)) == (X Y ...)

People should familiarize themselves a bit with Lisp when working with
the Emacs Lisp source code.  I know the above identity can be confusing
_once_, in different situations, not only in `pcase', but it is
something on has to know anyway, and this is really not that difficult
or magical.


Michael.




^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: Instead of pcase
  2023-11-30 19:26                       ` Eli Zaretskii
  2023-11-30 20:30                         ` Michael Heerdegen via Emacs development discussions.
@ 2023-11-30 20:47                         ` João Távora
  2023-12-01  6:31                           ` Eli Zaretskii
  1 sibling, 1 reply; 342+ messages in thread
From: João Távora @ 2023-11-30 20:47 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: Lynn Winebarger, rms, dmitry, philipk, emacs-devel

On Thu, Nov 30, 2023 at 7:27 PM Eli Zaretskii <eliz@gnu.org> wrote:

> I think you are missing the point.  The point is that pcase has so
> many semi-magical syntax features that use punctuation characters in
> creative ways that every extra punctuation character presents a
> puzzle.  Faced with
>
>   (`(,hookfun . ,start ,end))
>
> one immediately asks himself why the period,
> where in "normal" Lisp expressions it would be completely
> redundant?

FWIW the period is pretty self-evident to me that it separates
a car from a cdr in given cell of a cons chain.

However, in your example this is an error, just as it is in
this "normal" expression if what you wanted was to construct
a list.

 `(,hookfun . ,start ,end)

So I think you probably meant

   `(,hookfun . (,start ,end))

And this is valid in both pcase and normal backquoted list
expressions.  Furthermore, here the period is _not_ redundant.

IMO what's relatively contrived in pcase-- but very well contrived
I should add -- is the use of the backtick and comma, whose
usual job is output and list construction, to do the reverse,
to express input and list destructure.

João



^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: Instead of pcase
  2023-11-30  3:37                               ` Richard Stallman
@ 2023-12-01  0:18                                 ` Dmitry Gutov
  2023-12-01  5:51                                   ` Emanuel Berg
                                                     ` (2 more replies)
  0 siblings, 3 replies; 342+ messages in thread
From: Dmitry Gutov @ 2023-12-01  0:18 UTC (permalink / raw)
  To: rms; +Cc: michael_heerdegen, emacs-devel

On 30/11/2023 05:37, Richard Stallman wrote:
> [[[ To any NSA and FBI agents reading my email: please consider    ]]]
> [[[ whether defending the US Constitution against all enemies,     ]]]
> [[[ foreign or domestic, requires you to follow Snowden's example. ]]]
> 
>    > I guess that's the point I wanted to underscore: that those pcase uses
>    > are more-or-less optimal in terms of complexity (for its ultimate
>    > goals), that in most cases it comes from the problem domain rather than
>    > from the solution.
> 
> I think the way you measure "complexity" is different from the way I
> measure it.  I suspect that your measure does not count the complexity
> of learning `pcase' -- that it assumes the reader knows that already.
> 
> That complexitu is what I am trying to eliminate.
> 
> I also think that you measure "complexity" as the opposite of terseness,
> so that a couple of uses of `match-set' is in your view "added complexity".
> However, terseness is what makes `pcase' more complex.

You haven't posted your conversion, but I suspect it was not just less 
terse, but it also forced the programmer to repeat the same sets of 
information: first, in the predicate, to check that the value has a 
certain structure, and then in the matcher, to deconstruct the structure 
and create a set of variable bindings.

This repetition both adds verbosity and increases the chance to make a 
mistake in one of the two places. But once you eliminate it, I believe 
the result has to look like a more verbose pcase. Choosing an new syntax 
should be possible (indeed, somebody posted a link to a similar 
construct in Racket which is more wordy), but then those who don't like 
high-level constructs probably won't like it either.



^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: Instead of pcase
  2023-11-29 12:56                                 ` Dmitry Gutov
@ 2023-12-01  3:17                                   ` Richard Stallman
  0 siblings, 0 replies; 342+ messages in thread
From: Richard Stallman @ 2023-12-01  3:17 UTC (permalink / raw)
  To: Dmitry Gutov; +Cc: michael_heerdegen, emacs-devel

[[[ To any NSA and FBI agents reading my email: please consider    ]]]
[[[ whether defending the US Constitution against all enemies,     ]]]
[[[ foreign or domestic, requires you to follow Snowden's example. ]]]

  > I just wanted you to assume that the existing code does what it should 
  > do (there exist only those cases that pcase matches, and the ones it 
  > does not, should not exist), and to try to rewrite it using a different 
  > syntax.

What I wanted, when I saw that code, was something different.  I
wanted to rewrite it in a way that I would find cleaner.

-- 
Dr Richard Stallman (https://stallman.org)
Chief GNUisance of the GNU Project (https://gnu.org)
Founder, Free Software Foundation (https://fsf.org)
Internet Hall-of-Famer (https://internethalloffame.org)





^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: Instead of pcase
  2023-12-01  0:18                                 ` Dmitry Gutov
@ 2023-12-01  5:51                                   ` Emanuel Berg
  2023-12-10  8:34                                     ` Alfred M. Szmidt
  2023-12-01  7:21                                   ` Eli Zaretskii
  2023-12-02  3:21                                   ` Richard Stallman
  2 siblings, 1 reply; 342+ messages in thread
From: Emanuel Berg @ 2023-12-01  5:51 UTC (permalink / raw)
  To: emacs-devel

Dmitry Gutov wrote:

> Choosing an new syntax should be possible (indeed, somebody
> posted a link to a similar construct in Racket which is more
> wordy), but then those who don't like high-level constructs
> probably won't like it either.

We had a very long and unpleasant discussion, now people are
instead working on things they think will be an improvement.
And maybe it will be, at least to those people! So let's leave
it at that for now perhaps, regardless of whatever it is
a much more constructive approach.

-- 
underground experts united
https://dataswamp.org/~incal




^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: Instead of pcase
  2023-11-30 20:30                         ` Michael Heerdegen via Emacs development discussions.
@ 2023-12-01  6:24                           ` Eli Zaretskii
  2023-12-01 15:47                             ` Michael Heerdegen via Emacs development discussions.
  0 siblings, 1 reply; 342+ messages in thread
From: Eli Zaretskii @ 2023-12-01  6:24 UTC (permalink / raw)
  To: Michael Heerdegen; +Cc: emacs-devel

> Date: Thu, 30 Nov 2023 21:30:00 +0100
> From:  Michael Heerdegen via "Emacs development discussions." <emacs-devel@gnu.org>
> 
> Eli Zaretskii <eliz@gnu.org> writes:
> 
> > I think you are missing the point.  The point is that pcase has so
> > many semi-magical syntax features that use punctuation characters in
> > creative ways that every extra punctuation character presents a
> > puzzle.  Faced with
> >
> >   (`(,hookfun . ,start ,end))
> 
> This is not a valid expression and will be rejected by the reader.  Was
> it a typo or did you think this would be valid?

It was taken from one of the posted examples, perhaps with a typo.
But that is not relevant.  Are you saying pcase doesn't have
constructs like (`(SOMETHING...), or that SOMETHING doesn't use
periods in places where they are redundant in "normal" ELisp code?

IOW, these details are not the point, the point is something else
entirely, see below.

> > one immediately asks himself why the period, where in "normal" Lisp
> > expressions it would be completely redundant?
> 
> As had been said: the syntax has been chosen intentionally to underline
> that it is important to view the matched thing as a cons instead of a
> list.

My point focuses on the problems this syntax causes to someone who
doesn't have intimate knowledge and a lot of practice with pcase.
Thus, it is a disadvantage.  Whether it is outweighed by advantages is
a separate discussion; my message just pointed out that the
disadvantage exists and is real, because Lynn seemed to be missing
that point.

> > The fact that it is there then leaves one wondering whether that
> > period has some "magical" meaning.
> 
> As an alternative one can have a look at the docstring.

It is a disadvantage if one needs to consult doc strings all the time
while reading code.  And in this case, the doc string is quite long
and highly non-trivial (and rightfully so, since the DSL is a rather
complex one).

> People should familiarize themselves a bit with Lisp when working with
> the Emacs Lisp source code.  I know the above identity can be confusing
> _once_, in different situations, not only in `pcase', but it is
> something on has to know anyway, and this is really not that difficult
> or magical.

If one bumps into such constructs very frequently, then eventually one
will become familiarized with them.  But if the frequency is low
enough, one could easily forget the details, and then one will need to
consult the documentation again the next time.

Please don't underestimate these difficulties, even if you don't share
them.



^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: Instead of pcase
  2023-11-30 20:47                         ` João Távora
@ 2023-12-01  6:31                           ` Eli Zaretskii
  2023-12-01  7:07                             ` Yuri Khan
                                               ` (3 more replies)
  0 siblings, 4 replies; 342+ messages in thread
From: Eli Zaretskii @ 2023-12-01  6:31 UTC (permalink / raw)
  To: João Távora; +Cc: owinebar, rms, dmitry, philipk, emacs-devel

> From: João Távora <joaotavora@gmail.com>
> Date: Thu, 30 Nov 2023 20:47:22 +0000
> Cc: Lynn Winebarger <owinebar@gmail.com>, rms@gnu.org, dmitry@gutov.dev, philipk@posteo.net, 
> 	emacs-devel@gnu.org
> 
> On Thu, Nov 30, 2023 at 7:27 PM Eli Zaretskii <eliz@gnu.org> wrote:
> 
> So I think you probably meant
> 
>    `(,hookfun . (,start ,end))
> 
> And this is valid in both pcase and normal backquoted list
> expressions.  Furthermore, here the period is _not_ redundant.

The validity is not the point I wanted to make.  The point I wanted to
make is that the accepted syntax includes unusual uses of the period
and other punctuation, some of which have special meaning.  And that
makes the code harder to read and understand.

Incidentally, the actual code from which this were taken is

      (`(,hookfun . (,start ,end ,collection . ,plist))

Which has _two_ periods, not one, which are AFAIU redundant, as far as
the Lisp reader is concerned.

> IMO what's relatively contrived in pcase-- but very well contrived
> I should add -- is the use of the backtick and comma, whose
> usual job is output and list construction, to do the reverse,
> to express input and list destructure.

Again, the point is not that the construct cannot be explained away or
interpreted correctly given enough time and consulting the docs.  The
point is the _effort_ required to understand this without being an
expert on using pcase.  That is the point Richard was making, and that
is the _only_ point I wanted Lynn to understand.



^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: Instead of pcase
  2023-12-01  6:31                           ` Eli Zaretskii
@ 2023-12-01  7:07                             ` Yuri Khan
  2023-12-01  8:10                               ` Eli Zaretskii
  2023-12-01  8:35                             ` Andreas Schwab
                                               ` (2 subsequent siblings)
  3 siblings, 1 reply; 342+ messages in thread
From: Yuri Khan @ 2023-12-01  7:07 UTC (permalink / raw)
  To: Eli Zaretskii
  Cc: João Távora, owinebar, rms, dmitry, philipk,
	emacs-devel

On Fri, 1 Dec 2023 at 13:32, Eli Zaretskii <eliz@gnu.org> wrote:

> Incidentally, the actual code from which this were taken is
>
>       (`(,hookfun . (,start ,end ,collection . ,plist))
>
> Which has _two_ periods, not one, which are AFAIU redundant, as far as
> the Lisp reader is concerned.

The first period and the parentheses are redundant but they are
helpful because they emphasize that the first element and the rest of
the list come from different places.

The second period is not redundant. It causes the (,start ,end
,collection . ,plist) to match any list of 3+ elements and the ,plist
binding to receive the remainder. Without the period, (,start ,end
,collection ,plist) would only match a list of exactly 4 elements, and
,plist would bind to the fourth.

Maybe you are implying ,x is equivalent to (\, x) and so `(,hookfun .
(,start ,end ,collection . ,plist)) could be written `((\, hookfun)
(\, start) (\, end) (\, collection) \, plist). To me, that would be…
point-less?



^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: Instead of pcase
  2023-12-01  0:18                                 ` Dmitry Gutov
  2023-12-01  5:51                                   ` Emanuel Berg
@ 2023-12-01  7:21                                   ` Eli Zaretskii
  2023-12-01  8:03                                     ` Manuel Giraud via Emacs development discussions.
  2023-12-02  3:21                                   ` Richard Stallman
  2 siblings, 1 reply; 342+ messages in thread
From: Eli Zaretskii @ 2023-12-01  7:21 UTC (permalink / raw)
  To: Dmitry Gutov; +Cc: rms, michael_heerdegen, emacs-devel

> Date: Fri, 1 Dec 2023 02:18:00 +0200
> Cc: michael_heerdegen@web.de, emacs-devel@gnu.org
> From: Dmitry Gutov <dmitry@gutov.dev>
> 
> Choosing an new syntax should be possible (indeed, somebody posted a
> link to a similar construct in Racket which is more wordy), but then
> those who don't like high-level constructs probably won't like it
> either.

I think the point is not with high-level vs lower-level constructs,
the point is with syntax and semantics that deviate significantly from
Emacs Lisp syntax and semantics.  Syntax that is natural in Emacs Lisp
and uses good mnemonics in its keywords is easy to understand at a
glance, whereas syntax that deviates requires a full understanding of
all the details before you can interpret the code.

For example, constructs such as the many with-SOMETHING macros we have
in Emacs are also higher-level than the actual code they expand into,
but code using these macros is very easy to understand because the
syntax is normative and the names of the macros are descriptive enough
to be mnemonically helpful.



^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: Instead of pcase
  2023-12-01  7:21                                   ` Eli Zaretskii
@ 2023-12-01  8:03                                     ` Manuel Giraud via Emacs development discussions.
  0 siblings, 0 replies; 342+ messages in thread
From: Manuel Giraud via Emacs development discussions. @ 2023-12-01  8:03 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: Dmitry Gutov, rms, michael_heerdegen, emacs-devel

Eli Zaretskii <eliz@gnu.org> writes:

[...]

> For example, constructs such as the many with-SOMETHING macros we have
> in Emacs are also higher-level than the actual code they expand into,
> but code using these macros is very easy to understand because the
> syntax is normative and the names of the macros are descriptive enough
> to be mnemonically helpful.

Yes but the with-SOMETHING macros also exist in Common Lisp and are also
easy to understand.  Most of the time, it reads as « execute this body
with this resource taken/opened/locked and eventually do some
house-keeping said resource ».  A pattern matching construct will, of
course, be more complex.
-- 
Manuel Giraud



^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: Instead of pcase
  2023-12-01  7:07                             ` Yuri Khan
@ 2023-12-01  8:10                               ` Eli Zaretskii
  2023-12-01  9:04                                 ` Andreas Schwab
  2023-12-01 10:13                                 ` João Távora
  0 siblings, 2 replies; 342+ messages in thread
From: Eli Zaretskii @ 2023-12-01  8:10 UTC (permalink / raw)
  To: Yuri Khan; +Cc: joaotavora, owinebar, rms, dmitry, philipk, emacs-devel

> From: Yuri Khan <yuri.v.khan@gmail.com>
> Date: Fri, 1 Dec 2023 14:07:40 +0700
> Cc: João Távora <joaotavora@gmail.com>, 
> 	owinebar@gmail.com, rms@gnu.org, dmitry@gutov.dev, philipk@posteo.net, 
> 	emacs-devel@gnu.org
> 
> On Fri, 1 Dec 2023 at 13:32, Eli Zaretskii <eliz@gnu.org> wrote:
> 
> > Incidentally, the actual code from which this were taken is
> >
> >       (`(,hookfun . (,start ,end ,collection . ,plist))
> >
> > Which has _two_ periods, not one, which are AFAIU redundant, as far as
> > the Lisp reader is concerned.
> 
> The first period and the parentheses are redundant but they are
> helpful because they emphasize that the first element and the rest of
> the list come from different places.
> 
> The second period is not redundant. It causes the (,start ,end
> ,collection . ,plist) to match any list of 3+ elements and the ,plist
> binding to receive the remainder. Without the period, (,start ,end
> ,collection ,plist) would only match a list of exactly 4 elements, and
> ,plist would bind to the fourth.

Exactly my point: these periods and other special characters are
"magic" in pcase, but not elsewhere in Lisp.  Sometimes they are just
for better readability, sometimes they are significant in other ways.



^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: Instead of pcase
  2023-12-01  6:31                           ` Eli Zaretskii
  2023-12-01  7:07                             ` Yuri Khan
@ 2023-12-01  8:35                             ` Andreas Schwab
  2023-12-01 10:02                             ` João Távora
  2023-12-01 16:04                             ` Michael Heerdegen via Emacs development discussions.
  3 siblings, 0 replies; 342+ messages in thread
From: Andreas Schwab @ 2023-12-01  8:35 UTC (permalink / raw)
  To: Eli Zaretskii
  Cc: João Távora, owinebar, rms, dmitry, philipk,
	emacs-devel

On Dez 01 2023, Eli Zaretskii wrote:

> Incidentally, the actual code from which this were taken is
>
>       (`(,hookfun . (,start ,end ,collection . ,plist))
>
> Which has _two_ periods, not one, which are AFAIU redundant, as far as
> the Lisp reader is concerned.

This is an intrinsic part of Lisp which has nothing at all to do with
pcase.  It is frequently used throughout the whole Emacs codebase.

-- 
Andreas Schwab, schwab@linux-m68k.org
GPG Key fingerprint = 7578 EB47 D4E5 4D69 2510  2552 DF73 E780 A9DA AEC1
"And now for something completely different."



^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: Instead of pcase
  2023-12-01  8:10                               ` Eli Zaretskii
@ 2023-12-01  9:04                                 ` Andreas Schwab
  2023-12-04  3:08                                   ` Richard Stallman
  2023-12-01 10:13                                 ` João Távora
  1 sibling, 1 reply; 342+ messages in thread
From: Andreas Schwab @ 2023-12-01  9:04 UTC (permalink / raw)
  To: Eli Zaretskii
  Cc: Yuri Khan, joaotavora, owinebar, rms, dmitry, philipk,
	emacs-devel

On Dez 01 2023, Eli Zaretskii wrote:

> Exactly my point: these periods and other special characters are
> "magic" in pcase, but not elsewhere in Lisp.

This is not true.  There is no magic at all in the use of this reader
feature which is totally lost after reading.  It is absolutely
impossible to detect its use afterwards.

-- 
Andreas Schwab, schwab@linux-m68k.org
GPG Key fingerprint = 7578 EB47 D4E5 4D69 2510  2552 DF73 E780 A9DA AEC1
"And now for something completely different."



^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: Instead of pcase
  2023-12-01  6:31                           ` Eli Zaretskii
  2023-12-01  7:07                             ` Yuri Khan
  2023-12-01  8:35                             ` Andreas Schwab
@ 2023-12-01 10:02                             ` João Távora
  2023-12-01 11:52                               ` Eli Zaretskii
  2024-01-09  5:33                               ` Stefan Kangas
  2023-12-01 16:04                             ` Michael Heerdegen via Emacs development discussions.
  3 siblings, 2 replies; 342+ messages in thread
From: João Távora @ 2023-12-01 10:02 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: owinebar, rms, dmitry, philipk, emacs-devel

On Fri, Dec 1, 2023 at 6:31 AM Eli Zaretskii <eliz@gnu.org> wrote:

> The validity is not the point I wanted to make.  The point I wanted to
> make is that the accepted syntax includes unusual uses of the period
> and other punctuation, some of which have special meaning.  And that
> makes the code harder to read and understand.
>
> Incidentally, the actual code from which this were taken is
>
>       (`(,hookfun . (,start ,end ,collection . ,plist))
>
> Which has _two_ periods, not one, which are AFAIU redundant, as far as
> the Lisp reader is concerned.

They are NOT redundant.  Meaning you can't simply take them out
and have the expression mean the same: that's what "redundant"
means to me, at least.

But like so often in programming, there are different ways to say the same.
In pcase as in normal list-making life, the above form is the same as.

  (`(,hookfun ,start ,end ,collection . plist))

So while it's reasonable to take issue with the author's choice of one
of many equivalent list-representing constructs, I don't think one
should blame their choice of 'pcase' here.

Personally, I don't really fault the author too much in this
case: if the thing to be destructured were an entry of an alist, I
actually like to see things represented in the original alternative.

As you probably know, one as a maintainer often has to work with
data structures that one didn't invent and wishes weren't like
they are.  Very often these structures are contorted, incrementally
evolving lists where certain positional elements mean certain things
for the structure.  One may be completely innocent of inventing
this spaghetti and yet one has to work with it.  This happens very
frequently in Emacs, it certainly happens to me.

> > IMO what's relatively contrived in pcase-- but very well contrived
> > I should add -- is the use of the backtick and comma, whose
> > usual job is output and list construction, to do the reverse,
> > to express input and list destructure.
>
> Again, the point is not that the construct cannot be explained away or
> interpreted correctly given enough time and consulting the docs.

First, I'd like to say that when I first met pcase, I used to share
your views and now I don't.  It's not that I encounter pcase on
constantly these days (I don't), it's just that I quickly changed my
view once someone gave me a piece of insight about it.  That insight
has already surfaced here, but perhaps has not been underlined enough.

So, in these emails, I'm trying to explain to you how to change your
view of these pcase constructs in a constructive way, to help speed
up your understanding of important parts of our code base.  I hope
this message gets across.  If you've already decided you will never
understand 'pcase' and will forever reach for the docs, that's a
legitimate  position, but it also means I can't be much help in
this sub-discussion.

It is _easy_ to explain that "scary" construct _if_ you learn to _lean_
on what should be probably existing knowledge.  No doc-consulting
necessary.

You take a backtick-starting construct with as many scary periods
things as you can find and then, say

`(,foo . (,bar . ,baz))

And then ask yourself: "what kind of list does this build if I just
let-bind foo, bar and baz to 42?". And then you answer yourself
"Why, it's the improper list (42 42 . 42) made up of just two cons
cells and 3 fixnums!".  So _that's_ the kind of list that can be
destructured with the pcase expression.

This solves the reading problem.  Now the writing problem. To author
new pcase patterns one uses more or less the same process.  One again
leans on one's existing knowledge of how the list structure would be
expressed with backtick-and-quote.  So once you know the list
structure in your mind you write it as a backtick-and-quote expression,
just as if you were going to craft that list (though you aren't of
course).  Then once you're happy with your expression, you may take it
and you put it in one of the BINDINGS left-hand part of a 'let'.
Then you rename that 'let' to 'pcase-let' and away you go!

HTH



^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: Instead of pcase
  2023-12-01  8:10                               ` Eli Zaretskii
  2023-12-01  9:04                                 ` Andreas Schwab
@ 2023-12-01 10:13                                 ` João Távora
  1 sibling, 0 replies; 342+ messages in thread
From: João Távora @ 2023-12-01 10:13 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: Yuri Khan, owinebar, rms, dmitry, philipk, emacs-devel

On Fri, Dec 1, 2023 at 8:10 AM Eli Zaretskii <eliz@gnu.org> wrote:

> Exactly my point: these periods and other special characters are
> "magic" in pcase, but not elsewhere in Lisp.  Sometimes they are just
> for better readability, sometimes they are significant in other ways.

What you're saying isn't correct, Eli.  That period you are pointing to
has _exactly_ the same magic "elsewhere in Lisp" as it does in "pcase".

Forget pcase for a minute.  "Elsewhere in Lisp", if all those 5 symbols
are bound, then your example (now corrected):

  `(,hookfun . (,start ,end ,collection . ,plist))

produces a list made up with four cons cells.

If you take out the periods:

  `(,hookfun (,start ,end ,collection ,plist))

This still produces a list, but now it's made up of six cons cells!
That's a world of difference.

In a different email, I've explained how, both in 'pcase' and "elsewhere
in Lisp", your example can be rewritten with one less period to still use
four cons cells exactly.

João



^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: Instead of pcase
  2023-12-01 10:02                             ` João Távora
@ 2023-12-01 11:52                               ` Eli Zaretskii
  2023-12-01 12:48                                 ` Dmitry Gutov
                                                   ` (2 more replies)
  2024-01-09  5:33                               ` Stefan Kangas
  1 sibling, 3 replies; 342+ messages in thread
From: Eli Zaretskii @ 2023-12-01 11:52 UTC (permalink / raw)
  To: João Távora; +Cc: owinebar, rms, dmitry, philipk, emacs-devel

> From: João Távora <joaotavora@gmail.com>
> Date: Fri, 1 Dec 2023 10:02:37 +0000
> Cc: owinebar@gmail.com, rms@gnu.org, dmitry@gutov.dev, philipk@posteo.net, 
> 	emacs-devel@gnu.org
> 
> On Fri, Dec 1, 2023 at 6:31 AM Eli Zaretskii <eliz@gnu.org> wrote:
> 
> So, in these emails, I'm trying to explain to you how to change your
> view of these pcase constructs in a constructive way

This is a misunderstanding: I'm not expressing _my_ views.  I'm
expressing the views of someone who bumps into this code the first or
the second time, and/or didn't yet have the advantage of someone
giving them "a piece of insight" that caused you to change your mind.
IOW, I'm expressing _your_ views before you changed your mind.

In Emacs development and maintenance, being able to look at stuff from
the POV of an innocent user or Lisp programmer is sometimes required
to realize the true impact of some constructs and features.  We cannot
regard that only from the height of our own knowledge and experience,
which usually far surpass those of many Emacs users and programmers.

> You take a backtick-starting construct with as many scary periods
> things as you can find and then, say
> 
> `(,foo . (,bar . ,baz))
> 
> And then ask yourself: "what kind of list does this build if I just
> let-bind foo, bar and baz to 42?". And then you answer yourself
> "Why, it's the improper list (42 42 . 42) made up of just two cons
> cells and 3 fixnums!".  So _that's_ the kind of list that can be
> destructured with the pcase expression.
> 
> This solves the reading problem.  Now the writing problem. To author
> new pcase patterns one uses more or less the same process.  One again
> leans on one's existing knowledge of how the list structure would be
> expressed with backtick-and-quote.  So once you know the list
> structure in your mind you write it as a backtick-and-quote expression,
> just as if you were going to craft that list (though you aren't of
> course).  Then once you're happy with your expression, you may take it
> and you put it in one of the BINDINGS left-hand part of a 'let'.
> Then you rename that 'let' to 'pcase-let' and away you go!

If this is that easy, then why do we need no less than 120 lines to
describe pcase in the doc string, and no less than 600 lines to
document its features in the ELisp manual?

You and others seem to assume that I'm against pcase, or that I'm
attacking its syntax, or don't understand it.  Andreas Schwab has even
gone as far as lecture me on the basics of the Lisp reader and the
syntax of Emacs Lisp, apparently under the assumption that I don't
understand that.  None of that is true.  All I'm trying to say is that
there _are_ inherent problems in the DSL whose knowledge is required
to understand code written using pcase, and that you and others should
recognize these inherent problems are real, even though you have
overcome them, and anyone could overcome them given enough time and
experience.



^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: Instead of pcase
  2023-12-01 11:52                               ` Eli Zaretskii
@ 2023-12-01 12:48                                 ` Dmitry Gutov
  2023-12-01 14:44                                   ` Eli Zaretskii
  2023-12-01 13:28                                 ` João Távora
  2023-12-01 16:25                                 ` Andreas Schwab
  2 siblings, 1 reply; 342+ messages in thread
From: Dmitry Gutov @ 2023-12-01 12:48 UTC (permalink / raw)
  To: Eli Zaretskii, João Távora; +Cc: owinebar, rms, philipk, emacs-devel

On 01/12/2023 13:52, Eli Zaretskii wrote:
> If this is that easy, then why do we need no less than 120 lines to
> describe pcase in the doc string, and no less than 600 lines to
> document its features in the ELisp manual?

Most of those describe the extensions, or additional features, which are 
not essential to understanding the basics, to understand the examples 
which we were looking at in this thread.

> All I'm trying to say is that
> there_are_  inherent problems in the DSL whose knowledge is required
> to understand code written using pcase, and that you and others should
> recognize these inherent problems are real, even though you have
> overcome them, and anyone could overcome them given enough time and
> experience.

Most of us can agree that these DLS have associated costs.

Whether they are "problems" (to be fixed?), meaning the costs outweigh 
the benefits, seems to be the main theme of this thread.



^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: Instead of pcase
  2023-12-01 11:52                               ` Eli Zaretskii
  2023-12-01 12:48                                 ` Dmitry Gutov
@ 2023-12-01 13:28                                 ` João Távora
  2023-12-01 16:25                                 ` Andreas Schwab
  2 siblings, 0 replies; 342+ messages in thread
From: João Távora @ 2023-12-01 13:28 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: owinebar, rms, dmitry, philipk, emacs-devel

On Fri, Dec 1, 2023 at 11:52 AM Eli Zaretskii <eliz@gnu.org> wrote:

> > So, in these emails, I'm trying to explain to you how to change your
> > view of these pcase constructs in a constructive way
>
> This is a misunderstanding: I'm not expressing _my_ views.  I'm
> expressing the views of someone who bumps into this code the first or
> the second time, and/or didn't yet have the advantage of someone
> giving them "a piece of insight" that caused you to change your mind.
> IOW, I'm expressing _your_ views before you changed your mind.

Fair enough.  Though, given your statements about the "redundancy"
of '.' and its different "magic" role in 'pcase' vs "elsewhere in Lisp"
one can be easily led to believe the contrary, because both those statements
are demonstrably false (at least in the only interpretation of them I
could find).

> In Emacs development and maintenance, being able to look at stuff from
> the POV of an innocent user or Lisp programmer is sometimes required
> to realize the true impact of some constructs and features.  We cannot
> regard that only from the height of our own knowledge and experience,
> which usually far surpass those of many Emacs users and programmers.

Again, this is perfectly fair.  Elisp, like many other languages,
has constructs for different levels of proficiency.  You wouldn't refrain
from using C functions or C typedefs just because it requires more knowledge
about the how the C language than a simple untyped program where everything
is inlined in main() and every piece of data is in an array.

> If this is that easy, then why do we need no less than 120 lines to
> describe pcase in the doc string, and no less than 600 lines to
> document its features in the ELisp manual?

_I_ didn't write that docstring.  Maybe the docstring and the manual
should start by making the easy and common use cases prominent and
visible, just like I tried to do in that 10 line paragraph.  As you know,
writing good docstrings and manuals is a challenge in itself.  But that
shouldn't  be an argument against the validity of the tool being
described.

> understand that.  None of that is true.  All I'm trying to say is that
> there _are_ inherent problems in the DSL whose knowledge is required
> to understand code written using pcase, and that you and others should
> recognize these inherent problems are real

The only _inherent_ difficulty I recognize in pcase DSL's is the _inherit_
difficulty in understand the backtick-and-quote in so-called "normal Lisp".

> , even though you have
> overcome them, and anyone could overcome them given enough time and
> experience.

My point is that "time and experience" isn't necessary to understand
the most common uses of pcase's DSL.  That one piece of insight paired
a knowledge about how backtick-and-quote works "in normal Lisp"
for list construction will suffice to fully master pcase's list
destructuring abilities.



^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: Instead of pcase
  2023-12-01 12:48                                 ` Dmitry Gutov
@ 2023-12-01 14:44                                   ` Eli Zaretskii
  2023-12-01 18:28                                     ` Dmitry Gutov
  0 siblings, 1 reply; 342+ messages in thread
From: Eli Zaretskii @ 2023-12-01 14:44 UTC (permalink / raw)
  To: Dmitry Gutov; +Cc: joaotavora, owinebar, rms, philipk, emacs-devel

> Date: Fri, 1 Dec 2023 14:48:22 +0200
> Cc: owinebar@gmail.com, rms@gnu.org, philipk@posteo.net, emacs-devel@gnu.org
> From: Dmitry Gutov <dmitry@gutov.dev>
> 
> On 01/12/2023 13:52, Eli Zaretskii wrote:
> > If this is that easy, then why do we need no less than 120 lines to
> > describe pcase in the doc string, and no less than 600 lines to
> > document its features in the ELisp manual?
> 
> Most of those describe the extensions, or additional features, which are 
> not essential to understanding the basics, to understand the examples 
> which we were looking at in this thread.

This doesn't match the reality.

The node "pcase Macro" holds over 400 lines.  The first 145 lines
describe the various feature of pcase itself.  The rest are examples
and caveats, but the very fact that we decided to have them there
means that pcase is not easy to understand.

The node "Extending pcase" is indeed about extensions, which is why I
didn't include its line count in the number above.

The node "Backquote Patterns" is actually part of the pcase
description in the "pcase Macro" node, and was moved to a separate
node for methodological and didactic reasons; it holds more than 100
lines.

The node "Destructuring with pcase Patterns" describes an important
part of pcase functionality.  At least the first 45 lines of it are
about pcase, even if you consider pcase-let etc. as "extensions".

So, even if you want to exclude "extensions and additional features",
the description takes 145+100+45=290 lines, or 400+100+45=545 if you
agree that all of the first node is documentation, not "extensions".
That's quite a lot, and we have all that for a reason: you may
remember the disputes and several significant edits that this section
went through, because the original, much shorter text was deemed
insufficient.

> > All I'm trying to say is that
> > there_are_  inherent problems in the DSL whose knowledge is required
> > to understand code written using pcase, and that you and others should
> > recognize these inherent problems are real, even though you have
> > overcome them, and anyone could overcome them given enough time and
> > experience.
> 
> Most of us can agree that these DLS have associated costs.

Then we agree.  I just attempted to broaden this agreement.

> Whether they are "problems" (to be fixed?), meaning the costs outweigh 
> the benefits, seems to be the main theme of this thread.

You read too much into the words.  "Problems" are not necessarily
something that must be fixed, and "costs" is not necessarily something
that need not be fixed.  Those are basically synonyms in this
discussion.



^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: Instead of pcase
  2023-12-01  6:24                           ` Eli Zaretskii
@ 2023-12-01 15:47                             ` Michael Heerdegen via Emacs development discussions.
  2023-12-01 16:07                               ` Eli Zaretskii
  2023-12-01 20:27                               ` Alan Mackenzie
  0 siblings, 2 replies; 342+ messages in thread
From: Michael Heerdegen via Emacs development discussions. @ 2023-12-01 15:47 UTC (permalink / raw)
  To: emacs-devel

Eli Zaretskii <eliz@gnu.org> writes:

> > This is not a valid expression and will be rejected by the reader.
> > Was it a typo or did you think this would be valid?
>
> It was taken from one of the posted examples, perhaps with a typo.
> But that is not relevant.

My question was meant sincerely.  Did you try to understand the syntax?
How?  What was or is still unclear to you?

> Are you saying pcase doesn't have
> constructs like (`(SOMETHING...), or that SOMETHING doesn't use
> periods in places where they are redundant in "normal" ELisp code?

Redundant - no.  May there be different redundant ways to express lists
- yes.

If you use a backquote pattern `SOMETHING in pcase, when SOMETHING
should match a cons (lists are conses), then SOMETHING will typically be
a cons.  The dot reader syntax is the canonical read syntax for conses.
This is not that weird.

> IOW, these details are not the point, the point is something else
> entirely, see below [...]

> My point focuses on the problems this syntax causes to someone who
> doesn't have intimate knowledge and a lot of practice with pcase.

It is repeatedly used a wording like "magical", as if that was an
argument.  Ok, this syntax makes one first wonder how it has to be
interpreted.  Happened to me, too.  But this (the wondering) takes only
seconds.  What happens after that?  Have people then seriously tried to
understand the syntax?  Where and why did they fail?  I heard nothing
about that.  Just a repetition that it looks "strange" or "magical" or
that one would expect a different syntax.

Given that cons cells and lists are fundamental building blocks of the
whole language, I had hoped to hear more about why understanding this
would be hard.  Nobody did that concretely apart from Richard.  And it
might be the case that his rewrite will reuse the backquote syntax.

> > As an alternative one can have a look at the docstring.
>
> It is a disadvantage if one needs to consult doc strings all the time
> while reading code.  And in this case, the doc string is quite long
> and highly non-trivial (and rightfully so, since the DSL is a rather
> complex one).

This is, or should, not be the case.  Sometimes one might need to recall
the argument order of 'let' or 'app', but more when writing code.

I don't ever need to consult the documentation of `pcase' when reading
code, apart from the case when additional pcase macros are involved
(like 'map').  And I don't have a good such a good memory for such
things.

And I use it only in rare circumstances, where possible I prefer `if',
`cond', and `if-let'.

> If one bumps into such constructs very frequently, then eventually one
> will become familiarized with them.  But if the frequency is low
> enough, one could easily forget the details, and then one will need to
> consult the documentation again the next time.

What I want to say is that if you need to consult documentation of
backquote syntax in pcase again and again, you might not have understood
it entirely.  This is my question: do people fail to understand the
concept, or don't they even try?

> Please don't underestimate these difficulties, even if you don't share
> them.

I still try to understand them.


Michael.




^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: Instead of pcase
  2023-12-01  6:31                           ` Eli Zaretskii
                                               ` (2 preceding siblings ...)
  2023-12-01 10:02                             ` João Távora
@ 2023-12-01 16:04                             ` Michael Heerdegen via Emacs development discussions.
  2023-12-01 16:33                               ` Eli Zaretskii
  3 siblings, 1 reply; 342+ messages in thread
From: Michael Heerdegen via Emacs development discussions. @ 2023-12-01 16:04 UTC (permalink / raw)
  To: emacs-devel

Eli Zaretskii <eliz@gnu.org> writes:

> Incidentally, the actual code from which this were taken is
>
>       (`(,hookfun . (,start ,end ,collection . ,plist))
>
> Which has _two_ periods, not one, which are AFAIU redundant, as far as
> the Lisp reader is concerned.

#+begin_src emacs-lisp
(let ((hookfun #'my-hookfun)
      (start 1) (end 99)
      (collection (list "foo" "bar"))
      (plist `((prop . val))))

  (pcase `(,hookfun . (,start ,end ,collection . ,plist))
    (`(,hookfun . (,start ,end ,collection . ,plist))
     (list hookfun start end collection plist))))
;; ==> (my-hookfun 1 99 ("foo" "bar") ((prop . val)))
#+end_src

The `pcase' pattern is _literally_ identical to a `backquote' call used
to create the same value.  Whatever problem you have with `pcase' also
exists for backquote.

Michael.




^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: Instead of pcase
  2023-12-01 15:47                             ` Michael Heerdegen via Emacs development discussions.
@ 2023-12-01 16:07                               ` Eli Zaretskii
  2023-12-01 20:27                               ` Alan Mackenzie
  1 sibling, 0 replies; 342+ messages in thread
From: Eli Zaretskii @ 2023-12-01 16:07 UTC (permalink / raw)
  To: Michael Heerdegen; +Cc: emacs-devel

> Date: Fri, 01 Dec 2023 16:47:51 +0100
> From:  Michael Heerdegen via "Emacs development discussions." <emacs-devel@gnu.org>
> 
> > My point focuses on the problems this syntax causes to someone who
> > doesn't have intimate knowledge and a lot of practice with pcase.
> 
> It is repeatedly used a wording like "magical", as if that was an
> argument.  Ok, this syntax makes one first wonder how it has to be
> interpreted.  Happened to me, too.  But this (the wondering) takes only
> seconds.  What happens after that?  Have people then seriously tried to
> understand the syntax?  Where and why did they fail?  I heard nothing
> about that.  Just a repetition that it looks "strange" or "magical" or
> that one would expect a different syntax.

You are asking me about what others have done.  I don't know.  I do
know that having understood this once doesn't mean one will remember
that the next time.  If the meaning is complicated enough, and the
next time is far enough from the previous one, one could simply
forget, and then will have to make the same effort understanding that
again.

> Given that cons cells and lists are fundamental building blocks of the
> whole language, I had hoped to hear more about why understanding this
> would be hard.  Nobody did that concretely apart from Richard.  And it
> might be the case that his rewrite will reuse the backquote syntax.

We shall see.

> > If one bumps into such constructs very frequently, then eventually one
> > will become familiarized with them.  But if the frequency is low
> > enough, one could easily forget the details, and then one will need to
> > consult the documentation again the next time.
> 
> What I want to say is that if you need to consult documentation of
> backquote syntax in pcase again and again, you might not have understood
> it entirely.  This is my question: do people fail to understand the
> concept, or don't they even try?

I'll let others answer this.  Me, I just want to tell that complicated
stuff frequently needs to be re-read several times before it sinks.
Especially if these time instances are far apart.



^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: Instead of pcase
  2023-12-01 11:52                               ` Eli Zaretskii
  2023-12-01 12:48                                 ` Dmitry Gutov
  2023-12-01 13:28                                 ` João Távora
@ 2023-12-01 16:25                                 ` Andreas Schwab
  2 siblings, 0 replies; 342+ messages in thread
From: Andreas Schwab @ 2023-12-01 16:25 UTC (permalink / raw)
  To: Eli Zaretskii
  Cc: João Távora, owinebar, rms, dmitry, philipk,
	emacs-devel

On Dez 01 2023, Eli Zaretskii wrote:

> attacking its syntax, or don't understand it.  Andreas Schwab has even
> gone as far as lecture me on the basics of the Lisp reader and the
> syntax of Emacs Lisp, apparently under the assumption that I don't
> understand that.  None of that is true.

Then why have you taken it up when it has nothing at all to do with
pcase?  That looked very much like you desperately tried to find a case
against pcase and failed.

-- 
Andreas Schwab, schwab@linux-m68k.org
GPG Key fingerprint = 7578 EB47 D4E5 4D69 2510  2552 DF73 E780 A9DA AEC1
"And now for something completely different."



^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: Instead of pcase
  2023-12-01 16:04                             ` Michael Heerdegen via Emacs development discussions.
@ 2023-12-01 16:33                               ` Eli Zaretskii
  0 siblings, 0 replies; 342+ messages in thread
From: Eli Zaretskii @ 2023-12-01 16:33 UTC (permalink / raw)
  To: Michael Heerdegen; +Cc: emacs-devel

> Date: Fri, 01 Dec 2023 17:04:09 +0100
> From:  Michael Heerdegen via "Emacs development discussions." <emacs-devel@gnu.org>
> 
> (let ((hookfun #'my-hookfun)
>       (start 1) (end 99)
>       (collection (list "foo" "bar"))
>       (plist `((prop . val))))
> 
>   (pcase `(,hookfun . (,start ,end ,collection . ,plist))
>     (`(,hookfun . (,start ,end ,collection . ,plist))
>      (list hookfun start end collection plist))))
> ;; ==> (my-hookfun 1 99 ("foo" "bar") ((prop . val)))
> #+end_src
> 
> The `pcase' pattern is _literally_ identical to a `backquote' call used
> to create the same value.  Whatever problem you have with `pcase' also
> exists for backquote.

I don't have any problems with pcase.



^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: Instead of pcase
  2023-12-01 14:44                                   ` Eli Zaretskii
@ 2023-12-01 18:28                                     ` Dmitry Gutov
  2023-12-01 18:40                                       ` Eli Zaretskii
  2023-12-01 18:45                                       ` João Távora
  0 siblings, 2 replies; 342+ messages in thread
From: Dmitry Gutov @ 2023-12-01 18:28 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: joaotavora, owinebar, rms, philipk, emacs-devel

On 01/12/2023 16:44, Eli Zaretskii wrote:
>> Date: Fri, 1 Dec 2023 14:48:22 +0200
>> Cc: owinebar@gmail.com, rms@gnu.org, philipk@posteo.net, emacs-devel@gnu.org
>> From: Dmitry Gutov <dmitry@gutov.dev>
>>
>> On 01/12/2023 13:52, Eli Zaretskii wrote:
>>> If this is that easy, then why do we need no less than 120 lines to
>>> describe pcase in the doc string, and no less than 600 lines to
>>> document its features in the ELisp manual?
>>
>> Most of those describe the extensions, or additional features, which are
>> not essential to understanding the basics, to understand the examples
>> which we were looking at in this thread.
> 
> This doesn't match the reality.
> 
> The node "pcase Macro" holds over 400 lines.  The first 145 lines
> describe the various feature of pcase itself.  The rest are examples
> and caveats, but the very fact that we decided to have them there
> means that pcase is not easy to understand.
> 
> The node "Extending pcase" is indeed about extensions, which is why I
> didn't include its line count in the number above.
> 
> The node "Backquote Patterns" is actually part of the pcase
> description in the "pcase Macro" node, and was moved to a separate
> node for methodological and didactic reasons; it holds more than 100
> lines.
> 
> The node "Destructuring with pcase Patterns" describes an important
> part of pcase functionality.  At least the first 45 lines of it are
> about pcase, even if you consider pcase-let etc. as "extensions".

That just reaffirms my understanding that the main problem with 'pcase' 
that we have is documentation. The nodes are written very bottom-up, 
whereas what's really needed for someone to understand the core usage, 
would look more like the first half of the node "Destructuring with 
‘pcase’ Patterns".

> So, even if you want to exclude "extensions and additional features",
> the description takes 145+100+45=290 lines, or 400+100+45=545 if you
> agree that all of the first node is documentation, not "extensions".
> That's quite a lot, and we have all that for a reason: you may
> remember the disputes and several significant edits that this section
> went through, because the original, much shorter text was deemed
> insufficient.

Looks like it's still insufficient.

Jim Porter's suggestions for improving the docs are in a separate thread 
("Improving 'pcase' documentation"), it really deserves more attention.

>>> All I'm trying to say is that
>>> there_are_  inherent problems in the DSL whose knowledge is required
>>> to understand code written using pcase, and that you and others should
>>> recognize these inherent problems are real, even though you have
>>> overcome them, and anyone could overcome them given enough time and
>>> experience.
>>
>> Most of us can agree that these DLS have associated costs.
> 
> Then we agree.  I just attempted to broaden this agreement.
> 
>> Whether they are "problems" (to be fixed?), meaning the costs outweigh
>> the benefits, seems to be the main theme of this thread.
> 
> You read too much into the words.  "Problems" are not necessarily
> something that must be fixed, and "costs" is not necessarily something
> that need not be fixed.  Those are basically synonyms in this
> discussion.

Hopefully this clarification can bring most of the argument to a close.



^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: Instead of pcase
  2023-12-01 18:28                                     ` Dmitry Gutov
@ 2023-12-01 18:40                                       ` Eli Zaretskii
  2023-12-01 18:45                                       ` João Távora
  1 sibling, 0 replies; 342+ messages in thread
From: Eli Zaretskii @ 2023-12-01 18:40 UTC (permalink / raw)
  To: Dmitry Gutov; +Cc: joaotavora, owinebar, rms, philipk, emacs-devel

> Date: Fri, 1 Dec 2023 20:28:43 +0200
> Cc: joaotavora@gmail.com, owinebar@gmail.com, rms@gnu.org,
>  philipk@posteo.net, emacs-devel@gnu.org
> From: Dmitry Gutov <dmitry@gutov.dev>
> 
> That just reaffirms my understanding that the main problem with 'pcase' 
> that we have is documentation. The nodes are written very bottom-up, 
> whereas what's really needed for someone to understand the core usage, 
> would look more like the first half of the node "Destructuring with 
> ‘pcase’ Patterns".

Suggestions to improve the documentation are always welcome.  However,
what we have now is the result of efforts by several people, so I'd
hesitate to conclude that the documentation is the main problem.

> Jim Porter's suggestions for improving the docs are in a separate thread 
> ("Improving 'pcase' documentation"), it really deserves more attention.

It already did get attention.  It will get much more when Jim posts
patches to the manual and the doc string.



^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: Instead of pcase
  2023-12-01 18:28                                     ` Dmitry Gutov
  2023-12-01 18:40                                       ` Eli Zaretskii
@ 2023-12-01 18:45                                       ` João Távora
  2024-01-09  5:36                                         ` Stefan Kangas
  1 sibling, 1 reply; 342+ messages in thread
From: João Távora @ 2023-12-01 18:45 UTC (permalink / raw)
  To: Dmitry Gutov; +Cc: Eli Zaretskii, owinebar, rms, philipk, emacs-devel

On Fri, Dec 1, 2023 at 6:28 PM Dmitry Gutov <dmitry@gutov.dev> wrote:

> That just reaffirms my understanding that the main problem with 'pcase'
> that we have is documentation. The nodes are written very bottom-up,
> whereas what's really needed for someone to understand the core usage,
> would look more like the first half of the node "Destructuring with
> ‘pcase’ Patterns".

+1

Instead of "11.4 Pattern-Matching Conditional", that section could
be called "Pcase and friends" or "The pcase family of macros family".

Though it is original use of pcase, pcase conditionals are just one
of the things you can do with it, and in my recent experience, not
necessarily the most common or useful one.  Also 'pcase-let' is
probably easier to understand than 'pcase', as it only does
destructuring and binding whereas the other macros do that and something
more on top.

Besides renaming, that section could start with a 11.4.1 "quick-start"
with some brief explanation about how pcase relates to backquote-and-tick
and with an example for 'pcase-let', not unlike the one that surfaced here.

If space allows,  an example for 'pcase' that introduces the conditional
macro can be added.

João



^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: Instead of pcase
  2023-12-01 15:47                             ` Michael Heerdegen via Emacs development discussions.
  2023-12-01 16:07                               ` Eli Zaretskii
@ 2023-12-01 20:27                               ` Alan Mackenzie
  2023-12-02 13:24                                 ` Michael Heerdegen via Emacs development discussions.
  2023-12-03  3:28                                 ` Richard Stallman
  1 sibling, 2 replies; 342+ messages in thread
From: Alan Mackenzie @ 2023-12-01 20:27 UTC (permalink / raw)
  To: Michael Heerdegen; +Cc: emacs-devel

Hello, Michael

On Fri, Dec 01, 2023 at 16:47:51 +0100, Michael Heerdegen via Emacs development discussions. wrote:
> Eli Zaretskii <eliz@gnu.org> writes:

> > > This is not a valid expression and will be rejected by the reader.
> > > Was it a typo or did you think this would be valid?

> > It was taken from one of the posted examples, perhaps with a typo.
> > But that is not relevant.

> My question was meant sincerely.  Did you try to understand the syntax?
> How?  What was or is still unclear to you?

> > Are you saying pcase doesn't have
> > constructs like (`(SOMETHING...), or that SOMETHING doesn't use
> > periods in places where they are redundant in "normal" ELisp code?

> Redundant - no.  May there be different redundant ways to express lists
> - yes.

> If you use a backquote pattern `SOMETHING in pcase, when SOMETHING
> should match a cons (lists are conses), then SOMETHING will typically be
> a cons.  The dot reader syntax is the canonical read syntax for conses.
> This is not that weird.

For some reason, I have little difficulty with dots in normal code, but
have more difficulty with dots in pcase patterns.  They must be being
used differently.

> > IOW, these details are not the point, the point is something else
> > entirely, see below [...]

> > My point focuses on the problems this syntax causes to someone who
> > doesn't have intimate knowledge and a lot of practice with pcase.

> It is repeatedly used a wording like "magical", as if that was an
> argument.  Ok, this syntax makes one first wonder how it has to be
> interpreted.  Happened to me, too.  But this (the wondering) takes only
> seconds.

It took many hours for me.

> What happens after that?  Have people then seriously tried to
> understand the syntax?  Where and why did they fail?  I heard nothing
> about that.  Just a repetition that it looks "strange" or "magical" or
> that one would expect a different syntax.

The syntax is confusing.  Before the introduction of pcase (without any
public discussion, as far as I can remember) a backslash meant what it
meant, as did a comma.  Now, if there are pcase's around I can't look at
code and see what it means.  For each backslash or comma, I've
consciously got to stop and inspect it to see whether it's a standard b
or c, or a pcase b or c.  They tend to be mixed up indiscriminately.

Also, special forms which had a fixed meaning have now become ambiguous -
and and or.  Again, it takes conscious inspection to determine whether
one of these has its standard meaning, or the very different pcase
meaning.

> Given that cons cells and lists are fundamental building blocks of the
> whole language, I had hoped to hear more about why understanding this
> would be hard.  Nobody did that concretely apart from Richard.  And it
> might be the case that his rewrite will reuse the backquote syntax.

See my previous paragraphs for part of the problem.

> > > As an alternative one can have a look at the docstring.

> > It is a disadvantage if one needs to consult doc strings all the time
> > while reading code.  And in this case, the doc string is quite long
> > and highly non-trivial (and rightfully so, since the DSL is a rather
> > complex one).

> This is, or should, not be the case.  Sometimes one might need to recall
> the argument order of 'let' or 'app', but more when writing code.

> I don't ever need to consult the documentation of `pcase' when reading
> code, apart from the case when additional pcase macros are involved
> (like 'map').  And I don't have a good such a good memory for such
> things.

I don't have a good memory for them, either.  When I have to read code
with pcase stuff in it, I can't read it fluently.  My consciousness is
continually having to guess what the various constructs mean, which is
demoralising.  I don't have this problem with non-pcase code which is
otherwise of the same difficulty.

> And I use it only in rare circumstances, where possible I prefer `if',
> `cond', and `if-let'.

I only use it when maintaining other people's code.

> > If one bumps into such constructs very frequently, then eventually one
> > will become familiarized with them.  But if the frequency is low
> > enough, one could easily forget the details, and then one will need to
> > consult the documentation again the next time.

> What I want to say is that if you need to consult documentation of
> backquote syntax in pcase again and again, you might not have understood
> it entirely.  This is my question: do people fail to understand the
> concept, or don't they even try?

It's not the concept, it's the details.  The documentation for pcase on
its own is probably bigger than that for all the standard Emacs Lisp flow
control constructs put together.

Another thing about pcase is that you can't usefully learn and use just
part of it.  It's all or nothing, and it's a terrific effor to learn at
once.  I don't recall anything like this difficulty learning, say,
regexps.  It also contrasts with something like German adjective endings,
where one can usefully learn, say, just those for the three forms of
nominative and accusative, and gradually extend one's fluency, say, when
a dative ending becomes needed.

> > Please don't underestimate these difficulties, even if you don't share
> > them.

> I still try to understand them.

Yes.  I hope I've done something to increase this understanding with this
post.

> Michael.

-- 
Alan Mackenzie (Nuremberg, Germany).



^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: Instead of pcase
  2023-11-30 19:14                     ` Lynn Winebarger
  2023-11-30 19:26                       ` Eli Zaretskii
@ 2023-12-02  3:20                       ` Richard Stallman
  2023-12-02  8:41                         ` Andreas Schwab
                                           ` (3 more replies)
  1 sibling, 4 replies; 342+ messages in thread
From: Richard Stallman @ 2023-12-02  3:20 UTC (permalink / raw)
  To: Lynn Winebarger; +Cc: dmitry, philipk, emacs-devel

[[[ To any NSA and FBI agents reading my email: please consider    ]]]
[[[ whether defending the US Constitution against all enemies,     ]]]
[[[ foreign or domestic, requires you to follow Snowden's example. ]]]

  > > But a person who is just starting to look at this code, and reads that
  > > function first, is likely to be impeded in starting to reach that sort
  > > of understanding.
  > >

  > I have to respectfully disagree - dotted pair notation is a pretty
  > fundamental part of LISP syntax, regardless of dialect.

That is true, but it is not pertinent to my finding that pcase code
confusing.  I know what dotted pairs mean, but I was not sure what
they meant in pcase patterns.

Likewise for Eli.  It is unkind and unhelpful to lecture him about
what dotted paris are.

-- 
Dr Richard Stallman (https://stallman.org)
Chief GNUisance of the GNU Project (https://gnu.org)
Founder, Free Software Foundation (https://fsf.org)
Internet Hall-of-Famer (https://internethalloffame.org)





^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: Instead of pcase
  2023-12-01  0:18                                 ` Dmitry Gutov
  2023-12-01  5:51                                   ` Emanuel Berg
  2023-12-01  7:21                                   ` Eli Zaretskii
@ 2023-12-02  3:21                                   ` Richard Stallman
  2 siblings, 0 replies; 342+ messages in thread
From: Richard Stallman @ 2023-12-02  3:21 UTC (permalink / raw)
  To: Dmitry Gutov; +Cc: michael_heerdegen, emacs-devel

[[[ To any NSA and FBI agents reading my email: please consider    ]]]
[[[ whether defending the US Constitution against all enemies,     ]]]
[[[ foreign or domestic, requires you to follow Snowden's example. ]]]

  > certain structure, and then in the matcher, to deconstruct the structure 
  > and create a set of variable bindings.

I think I posted the translations I came up with.  But I can't
recall after this long whether there was any additional repetition.

  > This repetition both adds verbosity and increases the chance to make a 
  > mistake in one of the two places.

If there was any additional repetition, it was a few tokens -- nothing
significant.  The complexity of pcase's terse domain specific language
is a significant obstacle.

  > This repetition both adds verbosity and increases the chance to make a 
  > mistake in one of the two places. But once you eliminate it, I believe 
  > the result has to look like a more verbose pcase.

My current version of cond* has only a tiny fraction of the complexity
of pcase.

-- 
Dr Richard Stallman (https://stallman.org)
Chief GNUisance of the GNU Project (https://gnu.org)
Founder, Free Software Foundation (https://fsf.org)
Internet Hall-of-Famer (https://internethalloffame.org)





^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: Instead of pcase
  2023-12-02  3:20                       ` Richard Stallman
@ 2023-12-02  8:41                         ` Andreas Schwab
  2023-12-02  9:02                           ` Philip Kaludercic
  2023-12-05  2:58                           ` Richard Stallman
  2023-12-02 14:33                         ` Michael Heerdegen via Emacs development discussions.
                                           ` (2 subsequent siblings)
  3 siblings, 2 replies; 342+ messages in thread
From: Andreas Schwab @ 2023-12-02  8:41 UTC (permalink / raw)
  To: Richard Stallman; +Cc: Lynn Winebarger, dmitry, philipk, emacs-devel

On Dez 01 2023, Richard Stallman wrote:

> confusing.  I know what dotted pairs mean, but I was not sure what
> they meant in pcase patterns.

They don't mean anything.  It's pure lisp syntax.

-- 
Andreas Schwab, schwab@linux-m68k.org
GPG Key fingerprint = 7578 EB47 D4E5 4D69 2510  2552 DF73 E780 A9DA AEC1
"And now for something completely different."



^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: Instead of pcase
  2023-12-02  8:41                         ` Andreas Schwab
@ 2023-12-02  9:02                           ` Philip Kaludercic
  2023-12-02 10:14                             ` Emanuel Berg
  2023-12-05  2:58                           ` Richard Stallman
  1 sibling, 1 reply; 342+ messages in thread
From: Philip Kaludercic @ 2023-12-02  9:02 UTC (permalink / raw)
  To: Andreas Schwab; +Cc: Richard Stallman, Lynn Winebarger, dmitry, emacs-devel

Andreas Schwab <schwab@linux-m68k.org> writes:

> On Dez 01 2023, Richard Stallman wrote:
>
>> confusing.  I know what dotted pairs mean, but I was not sure what
>> they meant in pcase patterns.
>
> They don't mean anything.  It's pure lisp syntax.

Right, the doc-string mentions this as well:

--8<---------------cut here---------------start------------->8---
-- `QPAT

Backquote-style pcase patterns: `QPAT
QPAT can take the following forms:
  (QPAT1 . QPAT2)       matches if QPAT1 matches the car and QPAT2 the cdr.
[...]
--8<---------------cut here---------------end--------------->8---

Just like cons-cells are the "real" constituents of a list, so
pattern-matching on a list "really" means pattern matching on
cons-cells.  I believe this is the kind of behaviour that would arise
naturally, whenever someone tries to re-implement this themselves.

As has been said many times already in this thread: All of this seems to
point in the direction that the main issue people are having is that of
documentation, and part of the problem might be that pcase is generating
its doc-string dynamically, which -- while cool -- might not present the
information in the most understandable way.

Another question I meant to raise, and forgive me if I missed it
somewhere in the remaining discussions, is those who find themselves
confused by `pcase':  Do you have experience with programming languages
that heavily rely on pattern matching and/or unification (ML, Haskell,
Prolog, ...)?  Myself having experience with this kind of programming,
all I had to do to understand `pcase' was to translate the existing
abstract notion I had to the syntax that `pcase' provides.  While I can
imagine that one is more prone to be confused, if trying to learn both
the syntax and the point of `pcase', assuming that this kind of
articulating oneself is not natural.



^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: Instead of pcase
  2023-12-02  9:02                           ` Philip Kaludercic
@ 2023-12-02 10:14                             ` Emanuel Berg
  2023-12-02 17:02                               ` Barry Fishman
  0 siblings, 1 reply; 342+ messages in thread
From: Emanuel Berg @ 2023-12-02 10:14 UTC (permalink / raw)
  To: emacs-devel

Philip Kaludercic wrote:

> As has been said many times already in this thread: All of
> this seems to point in the direction that the main issue
> people are having is that of documentation, and part of the
> problem might be that pcase is generating its doc-string
> dynamically, which -- while cool -- might not present the
> information in the most understandable way.

Haha, agreed :)

> Another question I meant to raise, and forgive me if
> I missed it somewhere in the remaining discussions, is those
> who find themselves confused by `pcase': Do you have
> experience with programming languages that heavily rely on
> pattern matching and/or unification (ML, Haskell, Prolog,
> ...)?

I have experience from all three of those, I think fiddling
with pattern matching in those can be quite neurotic to the
point I like Elisp better, but sometimes it, and `pcase', is
really useful.

I thought pattern matching with in particular Haskell was
neurotic because one would spend more time on it than one felt
was called for, but I think Haskell invited to that kind of
fiddling, I always thought of Elisp including `pcase' to be
much more calm and relaxed?

I don't know if there is something with pattern matching that
makes it take over the language, this I felt in languages like
Haskell a lot, in Erlang to some noticable extent, in SML
I didn't think of it as a problem at all.

In Elisp, I also don't think of it as a problem at all.
Maybe if one would have pattern matching in the function line
definition like we see in Haskell and Erlang, I think that
would be too much, but still maybe it is just me who does
things in a way that works for me, and everyone else is just
shooting the Emacs source so full of pattern matching this has
become a problem for the maintainers.

-- 
underground experts united
https://dataswamp.org/~incal




^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: Instead of pcase
  2023-12-01 20:27                               ` Alan Mackenzie
@ 2023-12-02 13:24                                 ` Michael Heerdegen via Emacs development discussions.
  2023-12-02 13:51                                   ` Emanuel Berg
  2023-12-04  3:11                                   ` Richard Stallman
  2023-12-03  3:28                                 ` Richard Stallman
  1 sibling, 2 replies; 342+ messages in thread
From: Michael Heerdegen via Emacs development discussions. @ 2023-12-02 13:24 UTC (permalink / raw)
  To: emacs-devel

Alan Mackenzie <acm@muc.de> writes:

> The syntax is confusing.  Before the introduction of pcase (without any
> public discussion, as far as I can remember) a backslash

[ ...you mean "backquote" I think... ]

> meant what it meant, as did a comma.  Now, if there are pcase's around
> I can't look at code and see what it means.  For each backslash or
> comma, I've consciously got to stop and inspect it to see whether it's
> a standard b or c, or a pcase b or c.  They tend to be mixed up
> indiscriminately.

Is this really your main problem?  The "meaning" of any values is
context dependent, also of syntax when any macros are used.  If you see
`t' you also have to look around how it is used.

What I could understand would be that the fact that backquote
expressions can appear in `pcase' patterns and as well in the branch
bodies could be confusing.  One might not see whether one is reading a
pattern description or a body.

> Also, special forms which had a fixed meaning have now become ambiguous -
> and and or.  Again, it takes conscious inspection to determine whether
> one of these has its standard meaning, or the very different pcase
> meaning.

So, would it help if they would be called differently, e.g. "pand" and
"por"?

> > I still try to understand them.
>
> Yes.  I hope I've done something to increase this understanding with this
> post.

This helped a bit, thank you.

I still wonder, among other things, whether a better documentation could
help people to build a better mental model so that they don't need to
consult the documentation again and again.

Und außerdem wünsche ich gute und schnelle [zwinker!] Fortschritte beim
Üben dieser schwierigen [zwinker!] Adjektivdeklinationen (selbst wenn
sich gelegentlich sogar mal ein Genitiv einschleichen sollte) - und eine
angenehme Vorwinterzeit - Schnee!.


Michael.




^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: Instead of pcase
  2023-12-02 13:24                                 ` Michael Heerdegen via Emacs development discussions.
@ 2023-12-02 13:51                                   ` Emanuel Berg
  2023-12-04  3:11                                   ` Richard Stallman
  1 sibling, 0 replies; 342+ messages in thread
From: Emanuel Berg @ 2023-12-02 13:51 UTC (permalink / raw)
  To: emacs-devel

Michael Heerdegen via "Emacs development discussions." wrote:

>> Also, special forms which had a fixed meaning have now
>> become ambiguous - and and or. Again, it takes conscious
>> inspection to determine whether one of these has its
>> standard meaning, or the very different pcase meaning.
>
> So, would it help if they would be called differently, e.g.
> "pand" and "por"?

And "ror" for `rx'?

Yeah, if one is skimming the code and expects to understand
all of it from just doing that, maybe "pand" and "por" are
better. But when you are inside something, pcase in this case,
it is pretty much understood that then the rules are defined
by that, not what is outside.

Maybe the maintainers felt at some point they were 100% fluent
with Elisp just by visual inspection with no manual decoding
in the brain whatsoever, and now they feel cl-lib and pcase
has ruined that fluency.

So maybe the options are either getting as fluent with cl-lib
and pcase as well, or, if that cannot be done, accepting that
the "good old Elisp" days of total fluency is gone and it is
not coming back.

-- 
underground experts united
https://dataswamp.org/~incal




^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: Instead of pcase
  2023-12-02  3:20                       ` Richard Stallman
  2023-12-02  8:41                         ` Andreas Schwab
@ 2023-12-02 14:33                         ` Michael Heerdegen via Emacs development discussions.
  2023-12-04  3:11                           ` Richard Stallman
  2023-12-02 18:01                         ` Lynn Winebarger
  2023-12-03  3:27                         ` Richard Stallman
  3 siblings, 1 reply; 342+ messages in thread
From: Michael Heerdegen via Emacs development discussions. @ 2023-12-02 14:33 UTC (permalink / raw)
  To: emacs-devel

Richard Stallman <rms@gnu.org> writes:

> Likewise for Eli.  It is unkind and unhelpful to lecture him about
> what dotted paris are.

I hope I didn't.  I did not understand that some, and which, of his
questions were rhetorical.  Or if the questions were his own questions.
That had not been really clear.  Might have been the case for others.

Michael.




^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: Instead of pcase
  2023-12-02 10:14                             ` Emanuel Berg
@ 2023-12-02 17:02                               ` Barry Fishman
  2023-12-02 20:25                                 ` Michael Heerdegen via Emacs development discussions.
  2023-12-03  4:30                                 ` Emanuel Berg
  0 siblings, 2 replies; 342+ messages in thread
From: Barry Fishman @ 2023-12-02 17:02 UTC (permalink / raw)
  To: emacs-devel


On 2023-12-02 11:14:19 +01, Emanuel Berg wrote:
> I thought pattern matching with in particular Haskell was
> neurotic because one would spend more time on it than one felt
> was called for, but I think Haskell invited to that kind of
> fiddling, I always thought of Elisp including `pcase' to be
> much more calm and relaxed?

Your sense of calm and relaxation about `pcase' does not seem to be
shared by a lot of people, who think of it as overly complex and ugly.

To me Haskell starts with just Scheme changed to fix every criticism
that has been make about Lisp whether it was valid or not.  But they end
up with something very different.

The Haskell pattern matching construct, unlike `pcase' is broken into
three independent steps.  First the declaration of types for each of the
variables to be extracted, although this is sometimes done automatically
by the (static) type system.  Then, the list of accepted patterns, given
in the form of constructors using the variables to build the patterns
being matched. Then possibly a list of tests to be tried on the values
of the matching variables.  And finally for the first valid "pattern"
and "guard" test, the code is execute using the extracted variables.

My example `proto-case' more resembled this, although I did not allow
for multiple guard clauses for each constructor match.  It did not use
back-quoting, but instead required used a prototype constructions add
those needed for each atomic type, or type class (in the sense of CLOS).

This is less powerful than `pcase', but didn't require a subset of
back-quoting merged with modified type specifier syntax in one new
`pcase' specific language.

But comparing what goes on in Haskell `case' vs. any pattern matching in a
Lisp like language is hard, primarily because Haskell evaluation rules
are so different from those of other languages.  Haskell is a curried,
non-strict, statically typed, syntactically complex language, so can
reorder code in ways that are very different than Elisp.  So simple
Haskell code can becomes very complex in Lisp, and simple Lisp code can
be very complex in Haskell.

But my issue with `pcase' is more related to that people will tend to
use it by copying and pasting its example cases (which they don't fully
understand), in places where a simpler syntax would be used.  This is
partly because Elisp does not have the simpler Common Lisp `typecase'
(it does have the discouraged `cl-typecase') and a more flexible 'case'
and Scheme like `cond' constructs that are easier to understand and use,
and work in most situations.

Yes, you can come up with `pcase' situations that are shorter or more
powerful, but its seems that the `pcase' proponents don't seem to be
able to provide obvious examples which show that power.

Without those examples people will tend to cut and paste code in places
where simpler more readable code could be use.

Their use of pointing to existing Elisp code using `pcase' involves
understanding the context of the code.  This makes giving the any
alternative examples harder to do, because it require understanding and
possibly restructuring more complex situations.

Its should be the burden on the proponents of a new feature to provide
useful examples of their construct in a simple explainable context, and
not the alternative.

I see the Haskell pattern matching given very little time in
introductory Haskell books, because its well formulated and easy to
understand in the context of the language.

Of course understanding Haskell, especially after being exposed to most
other languages, requires a mental reset that is not easy.  It took me
about four re-reads to gain any understanding what was going on, but I
was burdened with having used a lot of other languages.  It was the
first time I couldn't just recast things in terms of how I would do them
better in Lisp.

But using a constructor based rather than a backquote-splice/type-specifier
approach seems (to me) simpler to understand.

Or at least give an example of code (in a simple context) to show
`pcase' in something that shows its full power.

-- 
Barry Fishman




^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: Instead of pcase
  2023-12-02  3:20                       ` Richard Stallman
  2023-12-02  8:41                         ` Andreas Schwab
  2023-12-02 14:33                         ` Michael Heerdegen via Emacs development discussions.
@ 2023-12-02 18:01                         ` Lynn Winebarger
  2023-12-04  3:11                           ` Richard Stallman
  2023-12-03  3:27                         ` Richard Stallman
  3 siblings, 1 reply; 342+ messages in thread
From: Lynn Winebarger @ 2023-12-02 18:01 UTC (permalink / raw)
  To: Richard Stallman; +Cc: Dmitry Gutov, Philip Kaludercic, emacs-devel

[-- Attachment #1: Type: text/plain, Size: 2199 bytes --]

On Fri, Dec 1, 2023, 10:20 PM Richard Stallman <rms@gnu.org> wrote:

>   > > But a person who is just starting to look at this code, and reads
> that
>   > > function first, is likely to be impeded in starting to reach that
> sort
>   > > of understanding.
>   > >
>
>   > I have to respectfully disagree - dotted pair notation is a pretty
>   > fundamental part of LISP syntax, regardless of dialect.
>
> That is true, but it is not pertinent to my finding that pcase code
> confusing.  I know what dotted pairs mean, but I was not sure what
> they meant in pcase patterns.
>
> Likewise for Eli.  It is unkind and unhelpful to lecture him about
> what dotted paris are.
>

I don't believe stating a disagreement is lecturing.  My understanding is
that we (or at least Eli and my response to him) are discussing concern for
a hypothetical Elisp programmer, as Eli has (if I understood correctly) no
problem understanding pcase.

Maybe it would be more useful to say that LISP has at least 3 kinds of
syntax - read syntax, special forms, and macros (forms defined by a
function written in LISP itself).  The difference between special forms and
macros can largely be ignored, which is one of the special characteristics
of LISP.  The difference between read syntax and the latter two is more
substantial.  I think it's reasonable to expect a LISP programmer to
recognize distinct text expressions for which the lisp "read" primitive
produces identical S-exressions.  Those differences cannot have anything to
do with the LISP forms processed by the expander/evaluator.

That being said, it wouldn't hurt to have a table exhaustively list all
read syntax recognized by the reader in one place, for reference.  It can
be difficult to determine what a particular bit of LISP source code means
when it contains infrequently used characters, since LISP is very
permissive in the use of characters in symbols in general.

I just don't think this dotted pair concern is a credible criticism of
pcase.  Maybe of a particular style preferences or idioms of different
programmers, but it is orthogonal to pcase.  Why would it only be confusing
when used in a pcase form?  pcase is not read-level syntax.

Lynn

[-- Attachment #2: Type: text/html, Size: 3047 bytes --]

^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: Instead of pcase
  2023-12-02 17:02                               ` Barry Fishman
@ 2023-12-02 20:25                                 ` Michael Heerdegen via Emacs development discussions.
  2023-12-03  4:30                                 ` Emanuel Berg
  1 sibling, 0 replies; 342+ messages in thread
From: Michael Heerdegen via Emacs development discussions. @ 2023-12-02 20:25 UTC (permalink / raw)
  To: emacs-devel

Barry Fishman <barry@ecubist.org> writes:

> Or at least give an example of code (in a simple context) to show
> `pcase' in something that shows its full power.

I suggest to have a look at the examples I had posted as a response to
a similar request by Richard.

Michael.




^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: Instead of pcase
  2023-11-28  6:35                               ` Nikita Domnitskii
  2023-11-30  3:37                                 ` Richard Stallman
@ 2023-12-02 21:37                                 ` Lynn Winebarger
  1 sibling, 0 replies; 342+ messages in thread
From: Lynn Winebarger @ 2023-12-02 21:37 UTC (permalink / raw)
  To: Nikita Domnitskii; +Cc: Richard Stallman, michael_heerdegen, emacs-devel

[-- Attachment #1: Type: text/plain, Size: 3418 bytes --]

On Tue, Nov 28, 2023, 8:54 AM Nikita Domnitskii <nikita@domnitskii.me>
wrote:

> Richard Stallman <rms@gnu.org> writes:
>
> >   (cond* (:bind b1 (b (save-window-excursion (find-file-at-point
> filename))))
> >          ((bufferp b) (setq b1 b))
> >          ((bufferp (car-safe b)) (setq b1 (car-safe b))))
> >   (if b1 (switch-to-buffer-other-window b)))
> >
> >   (cond* (:bind b1 (b (save-window-excursion (find-file-at-point
> filename))))
> >          ((bufferp b) (switch-to-buffer-other-window b))
> >          ((bufferp (car-safe b)) (switch-to-buffer-other-window
> (car-safe b)))))
> >
> >   (let ((b (save-window-excursion (find-file-at-point filename))) b1)
> >     (if (or (match-set b1 b (bufferp b1))
> >             (match-set b1 (car-safe b) (bufferp b1)))
> >         (switch-to-buffer-other-window b1)))
>
> To be honest all variants look less expressive than original
> pcase.
>
> Maybe instead of trying to implement cond* we should look into impoving
> pcase patterns? As a starting point I suggest Racket pattern matching
> implementation (which in my opinion is fairly readable):
> https://docs.racket-lang.org/reference/match.html


A similar match package is available in guile:
https://www.gnu.org/software/guile/manual/html_node/Pattern-Matching.html

Indeed, I first saw "match" in a course on compiler theory around 2000.
When I saw pcase I thought the author had based it on "match", but
according to  https://dl.acm.org/doi/pdf/10.1145/3386324 (Evolution of
Emacs Lisp, p 37), that resemblance was, at least initially, accidental.

As some others here have expressed, I find the use of "constructor syntax"
for both construction (in a value position) and destructuring (in a binding
position) aesthetically appealing.  On the other hand, since pcase is in
some ways an inverse operator to quasiquotation, I feel like the pattern
clauses should be implicitly backquoted.  Or, one might say, backquote
introduces a value context for constructor syntax, but is not itself part
of that constructor syntax, while unquote (comma) and unquote-splice
(comma-at) operators are constructor syntax.  Then pcase can be seen as
introducing a binding context (i.e. similar to the"cond-let" form being
discussed elsewhere).  Read syntax could also be introduced to formalize
the duality of the operators, say "`?".

The documentation of the "bare" patterns (un-backquoted) is probably the
most confusing part of the doc, especially with the "Caveats for symbol in
pattern" section, but that's how pcase is introduced(!).  That's where the
confusing DSL is to me, since operators like "and" and "or" are redefined
but act on patterns rather than values, but there's no visual prompt that
this redefinition is in effect. A similar complaint might be levelled at
",(and ...)".  If backquote and pcase were understood to introduce
evaluation and binding contexts respectively for constructor syntax, then
maybe the change in meaning would be more apparent?

There are also macro expanders written explicitly for syntax pattern
matching in Scheme.  Those might be adapted if the core developers would
prefer separate facilities for pattern matching used for compiling than
"low-level" facilities made available everywhere.  In a system like
"syntax-case" the bindings made by the matcher are only available in the
"syntax" constructor form, rather than bound as ordinary lexically-scoped
variables.


Lynn

[-- Attachment #2: Type: text/html, Size: 4688 bytes --]

^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: Instead of pcase
  2023-12-02  3:20                       ` Richard Stallman
                                           ` (2 preceding siblings ...)
  2023-12-02 18:01                         ` Lynn Winebarger
@ 2023-12-03  3:27                         ` Richard Stallman
  3 siblings, 0 replies; 342+ messages in thread
From: Richard Stallman @ 2023-12-03  3:27 UTC (permalink / raw)
  To: emacs-devel

[[[ To any NSA and FBI agents reading my email: please consider    ]]]
[[[ whether defending the US Constitution against all enemies,     ]]]
[[[ foreign or domestic, requires you to follow Snowden's example. ]]]

I foudn it necessary to add a little of the complexity of pcase, but
in a more elegant form.  Here's what I have now, for patterns to
match.


   **Possible types of patterns for :match and the match-... functions**

`CONSTANT

  A constant means to match any value equal to CONSTANT.

VARIABLE, a symbol

  A symbol means to match any value and set VARIABLE to it.

nil

  nil means to match any value and not store it anywhere.

Constrained variable, (TESTFN VARIABLE OTHER-ARGS...)

  This matches any value VALUE provided (TESTFN VALUE OTHER-ARGS...)
  evaluates to true.  If so, it sets VARIABLE to VALUE.

     (symbolp sym)    Match any symbol, store it in `sym'.
     (> num-foos 1)   Match any thing greater than 1, store it in `num-foos'.

  When matching to bind variables, this pattern unconditionally binds
  VARIABLE whether it matches or not.

  `quote', `constrain' and `or' cannot be used as TESTFN.

Constrained variable constructs can be nested.

  For example,

    (< (numberp num-foos) 1)  Match any number > 1,  store it in mum-foos.

General constrained variable, (constrain VAR EXPRESSION)

  This general constrained variable pattern binds VAR to the
  value being matched against, only for evaluating EXPRESSION.
  If the result is non-nil, the match succeeds
  and sets VAR to the value.

  For instance,

    (constrain x (and (> x 0) (< x 100)))

Multi-alternative, (or SUBPATTERNS...)

  This tries to match each of the SUBPATTERNS in order until one matches.
  If the pattern is being used to bind variables, it binds all the variables
  specified in any of SUBPATTERNS
\f
-- 
Dr Richard Stallman (https://stallman.org)
Chief GNUisance of the GNU Project (https://gnu.org)
Founder, Free Software Foundation (https://fsf.org)
Internet Hall-of-Famer (https://internethalloffame.org)





^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: Instead of pcase
  2023-12-01 20:27                               ` Alan Mackenzie
  2023-12-02 13:24                                 ` Michael Heerdegen via Emacs development discussions.
@ 2023-12-03  3:28                                 ` Richard Stallman
  1 sibling, 0 replies; 342+ messages in thread
From: Richard Stallman @ 2023-12-03  3:28 UTC (permalink / raw)
  To: Alan Mackenzie; +Cc: michael_heerdegen, emacs-devel

[[[ To any NSA and FBI agents reading my email: please consider    ]]]
[[[ whether defending the US Constitution against all enemies,     ]]]
[[[ foreign or domestic, requires you to follow Snowden's example. ]]]

What do you think of the `cond*' construct that I'm designing?
It's not finished, but what do you think of the current draft?
Do you find it clearer than pcase?

I hope so, but I'd like to check the reality.

-- 
Dr Richard Stallman (https://stallman.org)
Chief GNUisance of the GNU Project (https://gnu.org)
Founder, Free Software Foundation (https://fsf.org)
Internet Hall-of-Famer (https://internethalloffame.org)





^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: Instead of pcase
  2023-12-02 17:02                               ` Barry Fishman
  2023-12-02 20:25                                 ` Michael Heerdegen via Emacs development discussions.
@ 2023-12-03  4:30                                 ` Emanuel Berg
  1 sibling, 0 replies; 342+ messages in thread
From: Emanuel Berg @ 2023-12-03  4:30 UTC (permalink / raw)
  To: emacs-devel

Barry Fishman wrote:

>> I thought pattern matching with in particular Haskell was
>> neurotic because one would spend more time on it than one
>> felt was called for, but I think Haskell invited to that
>> kind of fiddling, I always thought of Elisp including
>> `pcase' to be much more calm and relaxed?
>
> Your sense of calm and relaxation about `pcase' does not
> seem to be shared by a lot of people, who think of it as
> overly complex and ugly.

Perception is reality, even when that perception is
irrational. But in this case, I don't think anyone disapproved
of some of the maintainers saying they perceived `cl-lib' and
`pcase' to be sources of increased complexity, or that that
perception was irrational in any way. If it came across that
way, I don't think it was intentional from anyone.

It was just how the whole thing was perceived by other people,
they perceived it is a categorical stance, cl-lib and pcase
are the root of evil, and we don't feel the need to nuance or
discuss that with anyone because we are the maintainers. So if
those people perceived it in that way, be it correct or
incorrect, that was reality for them as well.

So this is were it got ugly to some extent alltho it was held
at a reasonable level for the most part.

It is good that people are working on cond* now and it'll be
interesting to use it if and when it gets added.
Probably increased complexity in terms of the so-called "DSLs"
introduced - but also increased expressiveness and power -
from cl-lib and pcase will remain, but if we add cond* and
improve documentation for cl-lib and pcase that can reduce the
negativity how the whole thing is perceived by some people,
and hopefully the kind of frustration that was felt can be
chanelled into something creative and ultimately beneficial
for our software.

-- 
underground experts united
https://dataswamp.org/~incal




^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: Instead of pcase
  2023-12-01  9:04                                 ` Andreas Schwab
@ 2023-12-04  3:08                                   ` Richard Stallman
  2023-12-04 11:58                                     ` Eli Zaretskii
  0 siblings, 1 reply; 342+ messages in thread
From: Richard Stallman @ 2023-12-04  3:08 UTC (permalink / raw)
  To: Andreas Schwab; +Cc: emacs-devel

[[[ To any NSA and FBI agents reading my email: please consider    ]]]
[[[ whether defending the US Constitution against all enemies,     ]]]
[[[ foreign or domestic, requires you to follow Snowden's example. ]]]

  > This is not true.  There is no magic at all in the use of this reader
  > feature which is totally lost after reading.  It is absolutely
  > impossible to detect its use afterwards.

As a factual matter about dotted pairs in pcase patterns, that is
correct.

However, we have repeatedly seen that experienced Lispers, who would
have no trouble understanding those constructs in a backquote meant to
actually construct a structure of conses, don't know what to make of
them on encountering them in pcase patterns.

That's another factual matter about dotted pairs in pcase patterns.
It is more a psychological matter than a computational matter, but
that doesn't invalidate the observation.

It is part of the impact of complexity of pcase.


-- 
Dr Richard Stallman (https://stallman.org)
Chief GNUisance of the GNU Project (https://gnu.org)
Founder, Free Software Foundation (https://fsf.org)
Internet Hall-of-Famer (https://internethalloffame.org)





^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: Instead of pcase
  2023-12-02 18:01                         ` Lynn Winebarger
@ 2023-12-04  3:11                           ` Richard Stallman
  2023-12-04 12:27                             ` Lynn Winebarger
  0 siblings, 1 reply; 342+ messages in thread
From: Richard Stallman @ 2023-12-04  3:11 UTC (permalink / raw)
  To: Lynn Winebarger; +Cc: emacs-devel

[[[ To any NSA and FBI agents reading my email: please consider    ]]]
[[[ whether defending the US Constitution against all enemies,     ]]]
[[[ foreign or domestic, requires you to follow Snowden's example. ]]]

  > > Likewise for Eli.  It is unkind and unhelpful to lecture him about
  > > what dotted paris are.

  > I don't believe stating a disagreement is lecturing.

I was talking about the words you said to Eli to explain dotted pairs
to him.  I don't that they stated a disagreement, but they sure
sounded like lecturing.

-- 
Dr Richard Stallman (https://stallman.org)
Chief GNUisance of the GNU Project (https://gnu.org)
Founder, Free Software Foundation (https://fsf.org)
Internet Hall-of-Famer (https://internethalloffame.org)





^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: Instead of pcase
  2023-12-02 14:33                         ` Michael Heerdegen via Emacs development discussions.
@ 2023-12-04  3:11                           ` Richard Stallman
  0 siblings, 0 replies; 342+ messages in thread
From: Richard Stallman @ 2023-12-04  3:11 UTC (permalink / raw)
  To: Michael Heerdegen; +Cc: emacs-devel

[[[ To any NSA and FBI agents reading my email: please consider    ]]]
[[[ whether defending the US Constitution against all enemies,     ]]]
[[[ foreign or domestic, requires you to follow Snowden's example. ]]]

  > I hope I didn't.  I did not understand that some, and which, of his
  > questions were rhetorical.  Or if the questions were his own questions.
  > That had not been really clear.  Might have been the case for others.

I see that you're sincere about treating other people with respect,
and I respect that.  None of us is perfect.

-- 
Dr Richard Stallman (https://stallman.org)
Chief GNUisance of the GNU Project (https://gnu.org)
Founder, Free Software Foundation (https://fsf.org)
Internet Hall-of-Famer (https://internethalloffame.org)





^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: Instead of pcase
  2023-12-02 13:24                                 ` Michael Heerdegen via Emacs development discussions.
  2023-12-02 13:51                                   ` Emanuel Berg
@ 2023-12-04  3:11                                   ` Richard Stallman
  1 sibling, 0 replies; 342+ messages in thread
From: Richard Stallman @ 2023-12-04  3:11 UTC (permalink / raw)
  To: Michael Heerdegen; +Cc: emacs-devel

[[[ To any NSA and FBI agents reading my email: please consider    ]]]
[[[ whether defending the US Constitution against all enemies,     ]]]
[[[ foreign or domestic, requires you to follow Snowden's example. ]]]

  > Is this really your main problem?  The "meaning" of any values is
  > context dependent, also of syntax when any macros are used.

In principle, a macro can make any sort of transformations on the data
inside the macro form.  In practice, nearly all macros fall into a
limited range of syntax patters.  Macros that do drastic things with
syntax, such as `pcase', are few.  Most macros' syntax is obvious when
you see it.

-- 
Dr Richard Stallman (https://stallman.org)
Chief GNUisance of the GNU Project (https://gnu.org)
Founder, Free Software Foundation (https://fsf.org)
Internet Hall-of-Famer (https://internethalloffame.org)





^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: Instead of pcase
  2023-12-04  3:08                                   ` Richard Stallman
@ 2023-12-04 11:58                                     ` Eli Zaretskii
  2023-12-04 12:35                                       ` Lynn Winebarger
  2023-12-04 12:37                                       ` Dmitry Gutov
  0 siblings, 2 replies; 342+ messages in thread
From: Eli Zaretskii @ 2023-12-04 11:58 UTC (permalink / raw)
  To: rms; +Cc: schwab, emacs-devel

> From: Richard Stallman <rms@gnu.org>
> Cc: emacs-devel@gnu.org
> Date: Sun, 03 Dec 2023 22:08:21 -0500
> 
>   > This is not true.  There is no magic at all in the use of this reader
>   > feature which is totally lost after reading.  It is absolutely
>   > impossible to detect its use afterwards.
> 
> As a factual matter about dotted pairs in pcase patterns, that is
> correct.
> 
> However, we have repeatedly seen that experienced Lispers, who would
> have no trouble understanding those constructs in a backquote meant to
> actually construct a structure of conses, don't know what to make of
> them on encountering them in pcase patterns.
> 
> That's another factual matter about dotted pairs in pcase patterns.
> It is more a psychological matter than a computational matter, but
> that doesn't invalidate the observation.
> 
> It is part of the impact of complexity of pcase.

Some people are saying that everything is clear because the Lisp
reader does this and that.  But when humans read code, they don't
normally run the Lisp reader in their head, they use other techniques
to read and grasp what the code does.  If there's a need to ask what
does the Lisp reader do with some syntax, that is already an obstacle
to understanding the code, even though eventually one can understand
it, whether by thinking what the reader does or by actually running
the reader and/or macro-expansion.



^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: Instead of pcase
  2023-12-04  3:11                           ` Richard Stallman
@ 2023-12-04 12:27                             ` Lynn Winebarger
  0 siblings, 0 replies; 342+ messages in thread
From: Lynn Winebarger @ 2023-12-04 12:27 UTC (permalink / raw)
  To: Richard Stallman; +Cc: emacs-devel

[-- Attachment #1: Type: text/plain, Size: 842 bytes --]

On Sun, Dec 3, 2023, 10:11 PM Richard Stallman <rms@gnu.org> wrote:

>   > > Likewise for Eli.  It is unkind and unhelpful to lecture him about
>   > > what dotted paris are.
>
>   > I don't believe stating a disagreement is lecturing.
>
> I was talking about the words you said to Eli to explain dotted pairs
> to him.  I don't that they stated a disagreement, but they sure
> sounded like lecturing.
>

It's difficult for me to assess your statement with most of my text
removed.  I do tend to the pedantic (or precise), but this is a public
forum.  I'm not crafting my response specifically for the person I'm
responding to.  Without knowing the specific passages you find
objectionable, I can't tell if you think I'm talking down to Eli when I'm
trying to be clear for anyone reading, or if there is some other issue with
my prose.

Lynn

[-- Attachment #2: Type: text/html, Size: 1501 bytes --]

^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: Instead of pcase
  2023-12-04 11:58                                     ` Eli Zaretskii
@ 2023-12-04 12:35                                       ` Lynn Winebarger
  2023-12-04 13:20                                         ` Eli Zaretskii
  2023-12-04 12:37                                       ` Dmitry Gutov
  1 sibling, 1 reply; 342+ messages in thread
From: Lynn Winebarger @ 2023-12-04 12:35 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: Richard Stallman, schwab, emacs-devel

[-- Attachment #1: Type: text/plain, Size: 1772 bytes --]

On Mon, Dec 4, 2023, 6:58 AM Eli Zaretskii <eliz@gnu.org> wrote:

> > From: Richard Stallman <rms@gnu.org>
> > Cc: emacs-devel@gnu.org
> > Date: Sun, 03 Dec 2023 22:08:21 -0500
> >
> >   > This is not true.  There is no magic at all in the use of this reader
> >   > feature which is totally lost after reading.  It is absolutely
> >   > impossible to detect its use afterwards.
> >
> > As a factual matter about dotted pairs in pcase patterns, that is
> > correct.
> >
> > However, we have repeatedly seen that experienced Lispers, who would
> > have no trouble understanding those constructs in a backquote meant to
> > actually construct a structure of conses, don't know what to make of
> > them on encountering them in pcase patterns.
> >
> > That's another factual matter about dotted pairs in pcase patterns.
> > It is more a psychological matter than a computational matter, but
> > that doesn't invalidate the observation.
> >
> > It is part of the impact of complexity of pcase.
>
> Some people are saying that everything is clear because the Lisp
> reader does this and that.  But when humans read code, they don't
> normally run the Lisp reader in their head, they use other techniques
> to read and grasp what the code does.  If there's a need to ask what
> does the Lisp reader do with some syntax, that is already an obstacle
> to understanding the code, even though eventually one can understand
> it, whether by thinking what the reader does or by actually running
> the reader and/or macro-expansion.
>

I'm saying it makes no sense to me to lay the blame at the feet of the
pcase syntax.

Elisp will happily evaluate the expression
(if . ( t . (nil . (t . nil))))

Would you, or anyone, say that reflects some flaw in the design of the "if"
form?

Lynn

[-- Attachment #2: Type: text/html, Size: 2844 bytes --]

^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: Instead of pcase
  2023-12-04 11:58                                     ` Eli Zaretskii
  2023-12-04 12:35                                       ` Lynn Winebarger
@ 2023-12-04 12:37                                       ` Dmitry Gutov
  2023-12-08  3:54                                         ` Richard Stallman
  1 sibling, 1 reply; 342+ messages in thread
From: Dmitry Gutov @ 2023-12-04 12:37 UTC (permalink / raw)
  To: Eli Zaretskii, rms; +Cc: schwab, emacs-devel

On 04/12/2023 13:58, Eli Zaretskii wrote:
>> From: Richard Stallman<rms@gnu.org>
>> Cc:emacs-devel@gnu.org
>> Date: Sun, 03 Dec 2023 22:08:21 -0500
>>
>>    > This is not true.  There is no magic at all in the use of this reader
>>    > feature which is totally lost after reading.  It is absolutely
>>    > impossible to detect its use afterwards.
>>
>> As a factual matter about dotted pairs in pcase patterns, that is
>> correct.
>>
>> However, we have repeatedly seen that experienced Lispers, who would
>> have no trouble understanding those constructs in a backquote meant to
>> actually construct a structure of conses, don't know what to make of
>> them on encountering them in pcase patterns.
>>
>> That's another factual matter about dotted pairs in pcase patterns.
>> It is more a psychological matter than a computational matter, but
>> that doesn't invalidate the observation.
>>
>> It is part of the impact of complexity of pcase.
> Some people are saying that everything is clear because the Lisp
> reader does this and that.  But when humans read code, they don't
> normally run the Lisp reader in their head, they use other techniques
> to read and grasp what the code does.  If there's a need to ask what
> does the Lisp reader do with some syntax, that is already an obstacle
> to understanding the code, even though eventually one can understand
> it, whether by thinking what the reader does or by actually running
> the reader and/or macro-expansion.

Note that this subthread is not about pcase but about a particular 
instance where it was used together with the dotted syntax. In other 
places, people would use the dotted reader syntax inside a backquote 
without pcase, and the above considerations would stil apply.

Finally, in the example that was brought up, the dot syntax really *was* 
used to make comprehension more easy. But to see that you have to 
actually read the surrounding code and try to understand the data flow. 
And if the dotted syntax were not used, the spectator *would* have to 
conjure up the knowledge that (a . (b c)) is the same as (a b c). 
Whereas the current solution avoids that need.



^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: Instead of pcase
  2023-12-04 12:35                                       ` Lynn Winebarger
@ 2023-12-04 13:20                                         ` Eli Zaretskii
  2023-12-04 17:46                                           ` Andreas Schwab
  2023-12-04 18:17                                           ` Lynn Winebarger
  0 siblings, 2 replies; 342+ messages in thread
From: Eli Zaretskii @ 2023-12-04 13:20 UTC (permalink / raw)
  To: Lynn Winebarger; +Cc: rms, schwab, emacs-devel

> From: Lynn Winebarger <owinebar@gmail.com>
> Date: Mon, 4 Dec 2023 07:35:48 -0500
> Cc: Richard Stallman <rms@gnu.org>, schwab@linux-m68k.org,
>  emacs-devel <emacs-devel@gnu.org>
> 
> Elisp will happily evaluate the expression 
> (if . ( t . (nil . (t . nil))))
> 
> Would you, or anyone, say that reflects some flaw in the design of the "if" form?

No, but if someone writes such 'if' forms, I will ask them to rewrite
them.

IOW, the fact that the Lisp reader will happily read something does
not mean it is easily understandable by humans, or should freely be
used in Emacs.



^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: Instead of pcase
  2023-12-04 13:20                                         ` Eli Zaretskii
@ 2023-12-04 17:46                                           ` Andreas Schwab
  2023-12-07  2:48                                             ` Richard Stallman
  2023-12-04 18:17                                           ` Lynn Winebarger
  1 sibling, 1 reply; 342+ messages in thread
From: Andreas Schwab @ 2023-12-04 17:46 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: Lynn Winebarger, rms, emacs-devel

On Dez 04 2023, Eli Zaretskii wrote:

>> From: Lynn Winebarger <owinebar@gmail.com>
>> Date: Mon, 4 Dec 2023 07:35:48 -0500
>> Cc: Richard Stallman <rms@gnu.org>, schwab@linux-m68k.org,
>>  emacs-devel <emacs-devel@gnu.org>
>> 
>> Elisp will happily evaluate the expression 
>> (if . ( t . (nil . (t . nil))))
>> 
>> Would you, or anyone, say that reflects some flaw in the design of the "if" form?
>
> No, but if someone writes such 'if' forms, I will ask them to rewrite
> them.

There are 1802 occurrences of the sequence " . (" in the Emacs lisp
files.

-- 
Andreas Schwab, schwab@linux-m68k.org
GPG Key fingerprint = 7578 EB47 D4E5 4D69 2510  2552 DF73 E780 A9DA AEC1
"And now for something completely different."



^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: Instead of pcase
  2023-12-04 13:20                                         ` Eli Zaretskii
  2023-12-04 17:46                                           ` Andreas Schwab
@ 2023-12-04 18:17                                           ` Lynn Winebarger
  1 sibling, 0 replies; 342+ messages in thread
From: Lynn Winebarger @ 2023-12-04 18:17 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: Richard Stallman, schwab, emacs-devel

[-- Attachment #1: Type: text/plain, Size: 1247 bytes --]

On Mon, Dec 4, 2023, 8:20 AM Eli Zaretskii <eliz@gnu.org> wrote:

> > From: Lynn Winebarger <owinebar@gmail.com>
> > Date: Mon, 4 Dec 2023 07:35:48 -0500
> > Cc: Richard Stallman <rms@gnu.org>, schwab@linux-m68k.org,
> >  emacs-devel <emacs-devel@gnu.org>
> >
> > Elisp will happily evaluate the expression
> > (if . ( t . (nil . (t . nil))))
> >
> > Would you, or anyone, say that reflects some flaw in the design of the
> "if" form?
>
> No, but if someone writes such 'if' forms, I will ask them to rewrite
> them.
>
> IOW, the fact that the Lisp reader will happily read something does
> not mean it is easily understandable by humans, or should freely be
> used in Emacs.
>

Right, it's a style issue.

The issue Richard raised that I've begun to appreciate is that backquote is
redefined in the context of patterns in a way that is not compatible with
its definition everywhere else.  I don't think the same could be said of
the "," and ",@" read-syntax or symbols, because those symbols are not
defined as macros themselves, only as auxiliary syntax in the context of
quasiquotation.  It should be fine to incorporate them as auxiliary syntax
in the context of a destructuring macro, preferably with a reasonably
consistent semantics.

Lynn

[-- Attachment #2: Type: text/html, Size: 2304 bytes --]

^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: Instead of pcase
  2023-12-02  8:41                         ` Andreas Schwab
  2023-12-02  9:02                           ` Philip Kaludercic
@ 2023-12-05  2:58                           ` Richard Stallman
  2023-12-05  3:36                             ` chad
  1 sibling, 1 reply; 342+ messages in thread
From: Richard Stallman @ 2023-12-05  2:58 UTC (permalink / raw)
  To: Andreas Schwab; +Cc: emacs-devel

[[[ To any NSA and FBI agents reading my email: please consider    ]]]
[[[ whether defending the US Constitution against all enemies,     ]]]
[[[ foreign or domestic, requires you to follow Snowden's example. ]]]

  > > confusing.  I know what dotted pairs mean, but I was not sure what
  > > they meant in pcase patterns.

  > They don't mean anything.  It's pure lisp syntax.

I explained why I found it hard to understand that example.

Your response to my explanation is to argue with it.  To argue with
someone's explanation of why something was confusing does not change
teh fact that it was confusing.  You can either pay attention to the
cause, and perhaps reach a useful conclusion, or ignore the cause.
But ignoring it will not make the confusion not happen.

-- 
Dr Richard Stallman (https://stallman.org)
Chief GNUisance of the GNU Project (https://gnu.org)
Founder, Free Software Foundation (https://fsf.org)
Internet Hall-of-Famer (https://internethalloffame.org)





^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: Instead of pcase
  2023-12-05  2:58                           ` Richard Stallman
@ 2023-12-05  3:36                             ` chad
  2023-12-08  3:53                               ` Richard Stallman
  0 siblings, 1 reply; 342+ messages in thread
From: chad @ 2023-12-05  3:36 UTC (permalink / raw)
  To: rms; +Cc: Andreas Schwab, emacs-devel

[-- Attachment #1: Type: text/plain, Size: 1798 bytes --]

On Mon, Dec 4, 2023 at 9:59 PM Richard Stallman <rms@gnu.org> wrote:

>   > > confusing.  I know what dotted pairs mean, but I was not sure what
>   > > they meant in pcase patterns.
>
>   > They don't mean anything.  It's pure lisp syntax.
>
> I explained why I found it hard to understand that example.
>
> Your response to my explanation is to argue with it. [...]
>

I understand your point, and I don't disagree, but I do see another
viewpoint that also makes sense to me: that the misunderstanding is not in
the place that is being discussed. (In other words, that this is largely an
issue of mis-communication.)

The particular point that *I think* was being expressed but not effectively
communicated is this:

The example was cited as a place where pcase's use of special syntax lead
to confusion, but this the example doesn't use any special pcase syntax.
This doesn't remove the problem, but if it's correct, then it suggests that
the problem is perhaps more accurately described as "pcase makes some
experienced Lisp programmers so unsure about special syntax that they worry
it might be present where it is not". This could be a general problem with
any programming language, but is perhaps especially relevant to Lisp.

Coming back to the particular potential disagreement:

> I explained why I found it hard to understand that example.
>
> Your response to my explanation is to argue with it.

I *suspect* that the "argument* you see is not an attempt to tell you that
your explanation is wrong, but rather to suggest that the misunderstanding
might not be where you thought it was. (You are certainly correct that the
example was hard for you to understand, but you may or may not be correct
about the reasons.)

I hope that helps,
~Chad

[-- Attachment #2: Type: text/html, Size: 2351 bytes --]

^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: Instead of pcase
  2023-12-04 17:46                                           ` Andreas Schwab
@ 2023-12-07  2:48                                             ` Richard Stallman
  2023-12-07 17:42                                               ` Andreas Schwab
  0 siblings, 1 reply; 342+ messages in thread
From: Richard Stallman @ 2023-12-07  2:48 UTC (permalink / raw)
  To: Andreas Schwab; +Cc: eliz, owinebar, emacs-devel

[[[ To any NSA and FBI agents reading my email: please consider    ]]]
[[[ whether defending the US Constitution against all enemies,     ]]]
[[[ foreign or domestic, requires you to follow Snowden's example. ]]]

  > >> Elisp will happily evaluate the expression 
  > >> (if . ( t . (nil . (t . nil))))
  > >> 
  > >> Would you, or anyone, say that reflects some flaw in the design of the "if" form?
  > >
  > > No, but if someone writes such 'if' forms, I will ask them to rewrite
  > > them.

  > There are 1802 occurrences of the sequence " . (" in the Emacs lisp
  > files.

I will take your word for it -- but di you realize that you changed
the subject?   Occurrences of the sequence " . (" in the Emacs sources
are mostly not part of the issue at hand.

-- 
Dr Richard Stallman (https://stallman.org)
Chief GNUisance of the GNU Project (https://gnu.org)
Founder, Free Software Foundation (https://fsf.org)
Internet Hall-of-Famer (https://internethalloffame.org)





^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: Instead of pcase
  2023-12-07  2:48                                             ` Richard Stallman
@ 2023-12-07 17:42                                               ` Andreas Schwab
  2023-12-09  4:02                                                 ` Richard Stallman
  0 siblings, 1 reply; 342+ messages in thread
From: Andreas Schwab @ 2023-12-07 17:42 UTC (permalink / raw)
  To: Richard Stallman; +Cc: eliz, owinebar, emacs-devel

On Dez 06 2023, Richard Stallman wrote:

> I will take your word for it -- but di you realize that you changed
> the subject?

No, not at all.  It's 100% spot on.

-- 
Andreas Schwab, schwab@linux-m68k.org
GPG Key fingerprint = 7578 EB47 D4E5 4D69 2510  2552 DF73 E780 A9DA AEC1
"And now for something completely different."



^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: Instead of pcase
  2023-12-05  3:36                             ` chad
@ 2023-12-08  3:53                               ` Richard Stallman
  0 siblings, 0 replies; 342+ messages in thread
From: Richard Stallman @ 2023-12-08  3:53 UTC (permalink / raw)
  To: chad; +Cc: schwab, emacs-devel

[[[ To any NSA and FBI agents reading my email: please consider    ]]]
[[[ whether defending the US Constitution against all enemies,     ]]]
[[[ foreign or domestic, requires you to follow Snowden's example. ]]]

  > The example was cited as a place where pcase's use of special syntax lead
  > to confusion, but this the example doesn't use any special pcase syntax.
  > This doesn't remove the problem, but if it's correct, then it suggests that
  > the problem is perhaps more accurately described as "pcase makes some
  > experienced Lisp programmers so unsure about special syntax that they worry
  > it might be present where it is not".

I think you are right.  That is a clearer analysis of what happened to me,
and perhaps to Eli as well.

I don't think it affects the overall conclusions about pcase and its
syntax.  To some experienced Emacs Lisp hackers, they are confusing,
and that increases the effective complexity that they add to the Emacs
Lisp language.

-- 
Dr Richard Stallman (https://stallman.org)
Chief GNUisance of the GNU Project (https://gnu.org)
Founder, Free Software Foundation (https://fsf.org)
Internet Hall-of-Famer (https://internethalloffame.org)





^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: Instead of pcase
  2023-12-04 12:37                                       ` Dmitry Gutov
@ 2023-12-08  3:54                                         ` Richard Stallman
  0 siblings, 0 replies; 342+ messages in thread
From: Richard Stallman @ 2023-12-08  3:54 UTC (permalink / raw)
  To: Dmitry Gutov; +Cc: emacs-devel

[[[ To any NSA and FBI agents reading my email: please consider    ]]]
[[[ whether defending the US Constitution against all enemies,     ]]]
[[[ foreign or domestic, requires you to follow Snowden's example. ]]]

  > Note that this subthread is not about pcase but about a particular 
  > instance where it was used together with the dotted syntax.

That is true.  But please keep in mind that this example is presented
to people as a way to learn to understand pcase.

                                                                In other 
  > places, people would use the dotted reader syntax inside a backquote 
  > without pcase, and the above considerations would stil apply.

If "the above considerations" means the point that I raised, I don't
think they would.  My point was that that I am accustomed to reading,
and writing, backquote constructs with periods -- usually before
commas -- and I found this pcase hard to understand given that basis.

  > Finally, in the example that was brought up, the dot syntax really *was* 
  > used to make comprehension more easy. But to see that you have to 
  > actually read the surrounding code and try to understand the data flow. 

I did not come across in reading the code of a file.
I have never even seen the surrounding code.

I asked about what the valid options for that data would be, but got a
nonresponsive reply.

-- 
Dr Richard Stallman (https://stallman.org)
Chief GNUisance of the GNU Project (https://gnu.org)
Founder, Free Software Foundation (https://fsf.org)
Internet Hall-of-Famer (https://internethalloffame.org)





^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: Instead of pcase
  2023-12-07 17:42                                               ` Andreas Schwab
@ 2023-12-09  4:02                                                 ` Richard Stallman
  0 siblings, 0 replies; 342+ messages in thread
From: Richard Stallman @ 2023-12-09  4:02 UTC (permalink / raw)
  To: Andreas Schwab; +Cc: eliz, owinebar, emacs-devel

[[[ To any NSA and FBI agents reading my email: please consider    ]]]
[[[ whether defending the US Constitution against all enemies,     ]]]
[[[ foreign or domestic, requires you to follow Snowden's example. ]]]

  > > I will take your word for it -- but di you realize that you changed
  > > the subject?

  > No, not at all.  It's 100% spot on.

I suppose Eli and others will see that I am right.

-- 
Dr Richard Stallman (https://stallman.org)
Chief GNUisance of the GNU Project (https://gnu.org)
Founder, Free Software Foundation (https://fsf.org)
Internet Hall-of-Famer (https://internethalloffame.org)





^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: Instead of pcase
  2023-12-01  5:51                                   ` Emanuel Berg
@ 2023-12-10  8:34                                     ` Alfred M. Szmidt
  2023-12-10  9:35                                       ` Eli Zaretskii
  0 siblings, 1 reply; 342+ messages in thread
From: Alfred M. Szmidt @ 2023-12-10  8:34 UTC (permalink / raw)
  To: Emanuel Berg; +Cc: emacs-devel

[Seems this message didn't get pushed -- if it is a duplicate, apologies!]

   I am writing to express my concern about a recent change in the
   behavior of the jump-to-register and point-to-register commands in the
   master branch (Bug#66394).

It is also not mentioned in NEWS; unless you consider the cryptic entry:

  ** 'register-preview-delay' is no longer used.
  Register preview is no more delayed.  If you want to disable it use
  'register-use-preview' instead with a boolean value.

Setting register-use-preview to nil doesn't revert to the previous,
ancient, behaviour.  It also seems that this change removes the
possibility to add a delay -- which sounds like a nice feature,
specially _if_ after that delay you're asked for a explicit RET.

   Previously, these commands allowed users to seamlessly navigate
   without the need to press the RET key every time. Unfortunately, the
   recent modification has introduced a requirement to press RET with
   every use, which has proven to be quite cumbersome for me.

INCF.



^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: Instead of pcase
  2023-12-10  8:34                                     ` Alfred M. Szmidt
@ 2023-12-10  9:35                                       ` Eli Zaretskii
  2023-12-10  9:53                                         ` Alfred M. Szmidt
  0 siblings, 1 reply; 342+ messages in thread
From: Eli Zaretskii @ 2023-12-10  9:35 UTC (permalink / raw)
  To: Alfred M. Szmidt; +Cc: emacs-devel

> From: "Alfred M. Szmidt" <ams@gnu.org>
> Cc: emacs-devel@gnu.org
> Date: Sun, 10 Dec 2023 03:34:26 -0500
> 
> It is also not mentioned in NEWS; unless you consider the cryptic entry:
> 
>   ** 'register-preview-delay' is no longer used.
>   Register preview is no more delayed.  If you want to disable it use
>   'register-use-preview' instead with a boolean value.
> 
> Setting register-use-preview to nil doesn't revert to the previous,
> ancient, behaviour.

You have an outdated repository; please update from Git.

>                     It also seems that this change removes the
> possibility to add a delay -- which sounds like a nice feature,
> specially _if_ after that delay you're asked for a explicit RET.

That's why this is listed under "incompatible changes".  The feature
to disable the preview by setting the delay to a large value is
preserved, as described in NEWS, but the delaying is not.



^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: Instead of pcase
  2023-12-10  9:35                                       ` Eli Zaretskii
@ 2023-12-10  9:53                                         ` Alfred M. Szmidt
  2023-12-10 10:35                                           ` Eli Zaretskii
  0 siblings, 1 reply; 342+ messages in thread
From: Alfred M. Szmidt @ 2023-12-10  9:53 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: emacs-devel

   You have an outdated repository; please update from Git.

No, I don't.  register-use-preview set to nil does NOT revert to the
previous behaviour, and from the looks _purposefully_ so!



^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: Instead of pcase
  2023-12-10  9:53                                         ` Alfred M. Szmidt
@ 2023-12-10 10:35                                           ` Eli Zaretskii
  2023-12-10 11:05                                             ` Alfred M. Szmidt
  0 siblings, 1 reply; 342+ messages in thread
From: Eli Zaretskii @ 2023-12-10 10:35 UTC (permalink / raw)
  To: Alfred M. Szmidt; +Cc: emacs-devel

> From: "Alfred M. Szmidt" <ams@gnu.org>
> Cc: emacs-devel@gnu.org
> Date: Sun, 10 Dec 2023 04:53:33 -0500
> 
>    You have an outdated repository; please update from Git.
> 
> No, I don't.  register-use-preview set to nil does NOT revert to the
> previous behaviour, and from the looks _purposefully_ so!

The correct value is 'never', as the latest NEWS says.  Not nil.



^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: Instead of pcase
  2023-12-10 10:35                                           ` Eli Zaretskii
@ 2023-12-10 11:05                                             ` Alfred M. Szmidt
  0 siblings, 0 replies; 342+ messages in thread
From: Alfred M. Szmidt @ 2023-12-10 11:05 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: emacs-devel

   >    You have an outdated repository; please update from Git.
   > 
   > No, I don't.  register-use-preview set to nil does NOT revert to the
   > previous behaviour, and from the looks _purposefully_ so!

   The correct value is 'never', as the latest NEWS says.  Not nil.

Not according to the docstring.  Nor does it work as advertised, since
it does not revert to the previous behaviour in any shape or form.



^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: Instead of pcase
  2023-11-27  3:14                           ` Richard Stallman
  2023-11-28  2:46                             ` Richard Stallman
@ 2023-12-10 15:14                             ` Richard Stallman
  2023-12-10 16:27                               ` Lynn Winebarger
  1 sibling, 1 reply; 342+ messages in thread
From: Richard Stallman @ 2023-12-10 15:14 UTC (permalink / raw)
  To: Michael Heerdegen; +Cc: emacs-devel

[[[ To any NSA and FBI agents reading my email: please consider    ]]]
[[[ whether defending the US Constitution against all enemies,     ]]]
[[[ foreign or domestic, requires you to follow Snowden's example. ]]]

I am trying to rewrite `byte-optimize-letX' with cond*,
but I cannot understand its current definition.

Specifically, I can't understand this pcase clause:

    ;; Body is last variable.
    (`(,head ,(and bindings
                   (let last-var (caar (last bindings))))
             ,(and last-var             ; non-linear pattern
                   (pred symbolp) (pred (not keywordp)) (pred (not booleanp))))
     (if (eq head 'let)
         `(progn ,@(mapcar #'cadr bindings))
       `(,head ,(butlast bindings) ,(cadar (last bindings)))))

What case is it meant to handle?  What does that case look like?

The comments cited in that code make no sense to me; I don't know of
any use of `let' or `let*' in which the body would be one of the
variables, and their doc strings don't describe any new usage which
would make that meaningful.

-- 
Dr Richard Stallman (https://stallman.org)
Chief GNUisance of the GNU Project (https://gnu.org)
Founder, Free Software Foundation (https://fsf.org)
Internet Hall-of-Famer (https://internethalloffame.org)





^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: Instead of pcase
  2023-12-10 15:14                             ` Richard Stallman
@ 2023-12-10 16:27                               ` Lynn Winebarger
  2023-12-10 20:28                                 ` Michael Heerdegen via Emacs development discussions.
  2023-12-11  3:31                                 ` Richard Stallman
  0 siblings, 2 replies; 342+ messages in thread
From: Lynn Winebarger @ 2023-12-10 16:27 UTC (permalink / raw)
  To: Richard Stallman; +Cc: Michael Heerdegen, emacs-devel

[-- Attachment #1: Type: text/plain, Size: 1415 bytes --]

On Sun, Dec 10, 2023, 10:14 AM Richard Stallman <rms@gnu.org> wrote:

> [[[ To any NSA and FBI agents reading my email: please consider    ]]]
> [[[ whether defending the US Constitution against all enemies,     ]]]
> [[[ foreign or domestic, requires you to follow Snowden's example. ]]]
>
> I am trying to rewrite `byte-optimize-letX' with cond*,
> but I cannot understand its current definition.
>
> Specifically, I can't understand this pcase clause:
>
>     ;; Body is last variable.
>     (`(,head ,(and bindings
>                    (let last-var (caar (last bindings))))
>              ,(and last-var             ; non-linear pattern
>                    (pred symbolp) (pred (not keywordp)) (pred (not
> booleanp))))
>      (if (eq head 'let)
>          `(progn ,@(mapcar #'cadr bindings))
>        `(,head ,(butlast bindings) ,(cadar (last bindings)))))
>
> What case is it meant to handle?  What does that case look like?
>

The pattern would match a let or let* form that has bindings but no body.

If it's a let form, the bindings are unused since only code in the body
would see the bound variables.  So the optimization is to transform the
value expressions of the bindings into a progn.

If it's a let* form, then the last bound variables would only be visible in
the body, but there is none.  Therefore, the last variable binding is
eliminated and its value expression is made into the body.

Lynn

[-- Attachment #2: Type: text/html, Size: 2032 bytes --]

^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: Instead of pcase
  2023-12-10 16:27                               ` Lynn Winebarger
@ 2023-12-10 20:28                                 ` Michael Heerdegen via Emacs development discussions.
  2023-12-10 21:13                                   ` Lynn Winebarger
  2023-12-12  3:43                                   ` Richard Stallman
  2023-12-11  3:31                                 ` Richard Stallman
  1 sibling, 2 replies; 342+ messages in thread
From: Michael Heerdegen via Emacs development discussions. @ 2023-12-10 20:28 UTC (permalink / raw)
  To: emacs-devel

Lynn Winebarger <owinebar@gmail.com> writes:

> The pattern would match a let or let* form that has bindings but no
> body.

No - it matches where the body is the last variable.  Not an empty body
- right?

With other words this case:

#+begin_src emacs-lisp
(byte-optimize-letX
 '(let ((a (+ 1 x))
        (b (+ 2 x))
        (c (+ 3 x)))
    c))

; ==> (progn (+ 1 x) (+ 2 x) (+ 3 x))

(byte-optimize-letX
 '(let* ((a (+ 1 x))
         (b (+ 2 a))
         (c (+ 3 b)))
    c))

;; ==> (let* ((a (+ 1 x)) (b (+ 2 a)))
;;       (+ 3 b))
#+end_src


Michael.




^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: Instead of pcase
  2023-12-10 20:28                                 ` Michael Heerdegen via Emacs development discussions.
@ 2023-12-10 21:13                                   ` Lynn Winebarger
  2023-12-12  3:43                                   ` Richard Stallman
  1 sibling, 0 replies; 342+ messages in thread
From: Lynn Winebarger @ 2023-12-10 21:13 UTC (permalink / raw)
  To: Michael Heerdegen; +Cc: emacs-devel

[-- Attachment #1: Type: text/plain, Size: 820 bytes --]

On Sun, Dec 10, 2023, 3:28 PM Michael Heerdegen via Emacs development
discussions. <emacs-devel@gnu.org> wrote:

> Lynn Winebarger <owinebar@gmail.com> writes:
>
> > The pattern would match a let or let* form that has bindings but no
> > body.
>
> No - it matches where the body is the last variable.  Not an empty body
> - right?
>

I stand corrected - looks like I miscounted parentheses and/or
misunderstood the scoping rules of non-linear pattern variables.  The
reasoning for the validity of the transformation is essentially the same,
except instead of no variable references in the body, there is exactly one
variable reference.

It seems like this could be generalized somewhat, particularly for let
forms, but I'm guessing this particular case is frequently generated by
macros or in the compiler itself.

Lynn

[-- Attachment #2: Type: text/html, Size: 1386 bytes --]

^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: Instead of pcase
  2023-12-10 16:27                               ` Lynn Winebarger
  2023-12-10 20:28                                 ` Michael Heerdegen via Emacs development discussions.
@ 2023-12-11  3:31                                 ` Richard Stallman
  1 sibling, 0 replies; 342+ messages in thread
From: Richard Stallman @ 2023-12-11  3:31 UTC (permalink / raw)
  To: Lynn Winebarger; +Cc: michael_heerdegen, emacs-devel

[[[ To any NSA and FBI agents reading my email: please consider    ]]]
[[[ whether defending the US Constitution against all enemies,     ]]]
[[[ foreign or domestic, requires you to follow Snowden's example. ]]]

  > The pattern would match a let or let* form that has bindings but no body.

Thanks.  Now I can figure out what to do.

-- 
Dr Richard Stallman (https://stallman.org)
Chief GNUisance of the GNU Project (https://gnu.org)
Founder, Free Software Foundation (https://fsf.org)
Internet Hall-of-Famer (https://internethalloffame.org)





^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: Instead of pcase
  2023-12-10 20:28                                 ` Michael Heerdegen via Emacs development discussions.
  2023-12-10 21:13                                   ` Lynn Winebarger
@ 2023-12-12  3:43                                   ` Richard Stallman
  2023-12-12  6:46                                     ` Tomas Hlavaty
                                                       ` (4 more replies)
  1 sibling, 5 replies; 342+ messages in thread
From: Richard Stallman @ 2023-12-12  3:43 UTC (permalink / raw)
  To: Michael Heerdegen; +Cc: emacs-devel

[[[ To any NSA and FBI agents reading my email: please consider    ]]]
[[[ whether defending the US Constitution against all enemies,     ]]]
[[[ foreign or domestic, requires you to follow Snowden's example. ]]]

I think whoever wrote that code in byte-optimize-letX was fascinated
by the challenge of writing as much as possible in pcase language
and minimizing use of Lisp.

Here's my version, which I think is a lot clearer.

It illustrates some of the flexibility of cond*:
* Use of ordinary Lisp fir conditions,
* Matching against different objects.
* Clauses that bind and then drop through.

(defun byte-optimize-letX (form)
  (cond*
    ;; Bindings list is empty.
    (:match (`(,_ () . ,body) form)
     `(progn . ,body))

    ;; Decompose the form
    (:match (`(,head ,bindings . ,body) form))

    ;; Body is empty or just contains a constant.
    (:match ((or `() `(,(macroexp-const-p const))) body)
     ;; If the match succeeds, it always binds CONST.
     (if (eq head 'let)
         `(progn ,@(mapcar #'cadr bindings) ,const)
       `(,head ,(butlast bindings) ,(cadar (last bindings)) ,const)))

    ;; Body does nothing but return the last variable in bindings.
    ((let ((last-var (car-safe (car (last bindings)))))
       ;; Next line could be written using `match',
       ;; but the clarity of this is worth one cons.
       (and (symbolp last-var) (equal body (list last-var))))
     (if (eq head 'let)
         `(progn ,@(mapcar #'cadr bindings))
       `(,head ,(butlast bindings) ,(cadar (last bindings)))))

    (t form)))

-- 
Dr Richard Stallman (https://stallman.org)
Chief GNUisance of the GNU Project (https://gnu.org)
Founder, Free Software Foundation (https://fsf.org)
Internet Hall-of-Famer (https://internethalloffame.org)





^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: Instead of pcase
  2023-12-12  3:43                                   ` Richard Stallman
@ 2023-12-12  6:46                                     ` Tomas Hlavaty
  2023-12-12 15:18                                     ` [External] : " Drew Adams
                                                       ` (3 subsequent siblings)
  4 siblings, 0 replies; 342+ messages in thread
From: Tomas Hlavaty @ 2023-12-12  6:46 UTC (permalink / raw)
  To: rms, Michael Heerdegen; +Cc: emacs-devel

On Mon 11 Dec 2023 at 22:43, Richard Stallman <rms@gnu.org> wrote:
>      `(progn . ,body))

-> `(progn ,@body)

those dots everywhere are ugly



^ permalink raw reply	[flat|nested] 342+ messages in thread

* RE: [External] : Re: Instead of pcase
  2023-12-12  3:43                                   ` Richard Stallman
  2023-12-12  6:46                                     ` Tomas Hlavaty
@ 2023-12-12 15:18                                     ` Drew Adams
  2023-12-14  3:24                                       ` Richard Stallman
  2023-12-12 19:24                                     ` Tomas Hlavaty
                                                       ` (2 subsequent siblings)
  4 siblings, 1 reply; 342+ messages in thread
From: Drew Adams @ 2023-12-12 15:18 UTC (permalink / raw)
  To: rms@gnu.org, Michael Heerdegen; +Cc: emacs-devel@gnu.org

> I think whoever wrote that code in byte-optimize-letX was fascinated
> by the challenge of writing as much as possible in pcase language
> and minimizing use of Lisp.
> 
> Here's my version, which I think is a lot clearer.
> 
> It illustrates some of the flexibility of cond*:
> * Use of ordinary Lisp fir conditions,
> * Matching against different objects.
> * Clauses that bind and then drop through.
> 
> (defun byte-optimize-letX (form)
>   (cond*
>     ;; Bindings list is empty.
>     (:match (`(,_ () . ,body) form)
>      `(progn . ,body))
> 
>     ;; Decompose the form
>     (:match (`(,head ,bindings . ,body) form))
> 
>     ;; Body is empty or just contains a constant.
>     (:match ((or `() `(,(macroexp-const-p const))) body)
>      ;; If the match succeeds, it always binds CONST.
>      (if (eq head 'let)
>          `(progn ,@(mapcar #'cadr bindings) ,const)
>        `(,head ,(butlast bindings) ,(cadar (last bindings)) ,const)))
> 
>     ;; Body does nothing but return the last variable in bindings.
>     ((let ((last-var (car-safe (car (last bindings)))))
>        ;; Next line could be written using `match',
>        ;; but the clarity of this is worth one cons.
>        (and (symbolp last-var) (equal body (list last-var))))
>      (if (eq head 'let)
>          `(progn ,@(mapcar #'cadr bindings))
>        `(,head ,(butlast bindings) ,(cadar (last bindings)))))
> 
>     (t form)))


You might want to show the original, pcase,
version at the same time, for comparison.
___

It might be clearer if clauses that can end
the `cond*' are easily distinguished from
those that always continue on to the next
clause - their return value doesn't matter to
the control flow (e.g., they just match/bind).

Or is the former always the case if a clause
contains two successive sexps?  E.g., is the
second clause above the only one that always
"falls through" after performing its action
(matching & binding)?  If so, the absence or
presence of a second sexp in a clause
distinguishes the two cases enough, I guess.

^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: Instead of pcase
  2023-12-12  3:43                                   ` Richard Stallman
  2023-12-12  6:46                                     ` Tomas Hlavaty
  2023-12-12 15:18                                     ` [External] : " Drew Adams
@ 2023-12-12 19:24                                     ` Tomas Hlavaty
  2023-12-12 21:36                                       ` [External] : " Drew Adams
  2023-12-13  1:32                                     ` Adam Porter
  2023-12-13  4:58                                     ` Richard Stallman
  4 siblings, 1 reply; 342+ messages in thread
From: Tomas Hlavaty @ 2023-12-12 19:24 UTC (permalink / raw)
  To: rms, Michael Heerdegen; +Cc: emacs-devel

in plain lisp with much clearer control-flow (not tested):

(defun byte-optimize-letX (form)
  (if (consp form)
      (let ((head (car form))
            (bindings (cadr form))
            (body (cddr form)))
        (if bindings
            (let ((const (car body))
                  (rest (cdr body)))
              (if (or (not body)
                      (and (macroexp-const-p const)
                           (not rest)))
                  ;; Body is empty or a constant.
                  (if (eq head 'let)
                      `(progn
                         ,@(mapcar #'cadr bindings)
                         ,const)
                    `(,head
                      ,(butlast bindings)
                      ,(cadar (last bindings)) ,const))
                (if (let ((last-var (car-safe (car (last bindings)))))
                      (and (symbolp last-var)
                           (equal body (list last-var))))
                    ;; Body does nothing but return the last variable in bindings.
                    (if (eq head 'let)
                        `(progn
                           ,@(mapcar #'cadr bindings))
                      `(,head
                        ,(butlast bindings)
                        ,(cadar (last bindings))))
                  form))
              ;; Bindings list is empty.
              `(progn ,@body)))
        form)))



^ permalink raw reply	[flat|nested] 342+ messages in thread

* RE: [External] : Re: Instead of pcase
  2023-12-12 19:24                                     ` Tomas Hlavaty
@ 2023-12-12 21:36                                       ` Drew Adams
  2023-12-12 22:25                                         ` Michael Heerdegen via Emacs development discussions.
  0 siblings, 1 reply; 342+ messages in thread
From: Drew Adams @ 2023-12-12 21:36 UTC (permalink / raw)
  To: Tomas Hlavaty, rms@gnu.org, Michael Heerdegen; +Cc: emacs-devel@gnu.org

> in plain lisp with much clearer control-flow (not tested):
> 
> (defun byte-optimize-letX (form)
>   (if (consp form)
>       (let ((head (car form))
>             (bindings (cadr form))
>             (body (cddr form)))
>         (if bindings
>             (let ((const (car body))
>                   (rest (cdr body)))
>               (if (or (not body)
>                       (and (macroexp-const-p const)
>                            (not rest)))
>                   ;; Body is empty or a constant.
>                   (if (eq head 'let)
>                       `(progn
>                          ,@(mapcar #'cadr bindings)
>                          ,const)
>                     `(,head
>                       ,(butlast bindings)
>                       ,(cadar (last bindings)) ,const))
>                 (if (let ((last-var (car-safe (car (last bindings)))))
>                       (and (symbolp last-var)
>                            (equal body (list last-var))))
>                     ;; Body does nothing but return the last variable in
> bindings.
>                     (if (eq head 'let)
>                         `(progn
>                            ,@(mapcar #'cadr bindings))
>                       `(,head
>                         ,(butlast bindings)
>                         ,(cadar (last bindings))))
>                   form))
>               ;; Bindings list is empty.
>               `(progn ,@body)))
>         form)))

<nit>

Maybe a little clearer than (if (consp xxx)
                                (huge tree sexp)
                              xxx)
is (if (atom xxx)
       xxx
     (huge tree sexp))

I think more than a few folks forget about `atom', for
some reason.  (Sometimes I see (not (consp xxx)) or
even (!) (null (consp xxx)).)

</nit>




^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: [External] : Re: Instead of pcase
  2023-12-12 21:36                                       ` [External] : " Drew Adams
@ 2023-12-12 22:25                                         ` Michael Heerdegen via Emacs development discussions.
  0 siblings, 0 replies; 342+ messages in thread
From: Michael Heerdegen via Emacs development discussions. @ 2023-12-12 22:25 UTC (permalink / raw)
  To: emacs-devel

Drew Adams <drew.adams@oracle.com> writes:

> I think more than a few folks forget about `atom', for
> some reason.  (Sometimes I see (not (consp xxx)) or
> even (!) (null (consp xxx)).)

That should be (listp (consp xxx)) of course.

Michael.




^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: Instead of pcase
  2023-12-12  3:43                                   ` Richard Stallman
                                                       ` (2 preceding siblings ...)
  2023-12-12 19:24                                     ` Tomas Hlavaty
@ 2023-12-13  1:32                                     ` Adam Porter
  2023-12-14  3:23                                       ` Richard Stallman
                                                         ` (3 more replies)
  2023-12-13  4:58                                     ` Richard Stallman
  4 siblings, 4 replies; 342+ messages in thread
From: Adam Porter @ 2023-12-13  1:32 UTC (permalink / raw)
  To: rms; +Cc: emacs-devel

Hi Richard,

> I think whoever wrote that code in byte-optimize-letX was fascinated
> by the challenge of writing as much as possible in pcase language
> and minimizing use of Lisp.
> 
> Here's my version, which I think is a lot clearer.
> 
> It illustrates some of the flexibility of cond*:
> * Use of ordinary Lisp fir conditions,
> * Matching against different objects.
> * Clauses that bind and then drop through.

Respectfully, I disagree that this example is clearer than the original 
pcase form.[0]  I'll explain why:

> (defun byte-optimize-letX (form)
>   (cond*
>     ;; Bindings list is empty.
>     (:match (`(,_ () . ,body) form)
>      `(progn . ,body))

This is nearly identical to the equivalent pcase syntax, only adding 
`:match'.  Since pcase's (and I suppose cond*'s) purpose is pattern 
matching, this seems redundant and unnecessarily verbose.

>     ;; Decompose the form
>     (:match (`(,head ,bindings . ,body) form))

I suppose it is largely a matter of taste, but I strongly dislike 
fall-through clauses.  While it seems convenient here, as it allows the 
removal of either a redundancy (reiterating bindings in multiple 
clauses) or a level of nesting, its bindings are also implicit rather 
than explicit, as the scope of the binding form is not enclosed by 
visible boundaries (i.e. parens).

One also wonders what it would look like if such a cond* form had 
multiple, overlapping fall-through bindings of the same variables--that 
would seem to be necessary in some cases, and would likely be confusing.

Finally, forms which allow fall-through clauses are known to be more 
prone to human error than forms which don't allow them--and they don't 
seem syntactically "lispy."  So I think this is more confusing than 
pcase, not less.

>     ;; Body is empty or just contains a constant.
>     (:match ((or `() `(,(macroexp-const-p const))) body)

This seems even more confusing to me.  The equivalent pcase form is:

   `(,head ,bindings . ,(or '() `(,(and const (pred macroexp-const-p)))))

While the `and' keyword's being used to bind `const' may be surprising 
to those unfamiliar with pcase,[1] at least it explicitly binds the form 
to the variable before using it, and the scope of the binding is visible 
(being within that clause).

In contrast, the cond* example appears to implicitly bind `const' by the 
symbol's being present in the predicate form as an argument.  This seems 
much less clear to me.  It also seems error-prone, as in a case where 
`const' were already bound.

As well, what if the user needed to pass an already-bound argument in 
addition to the one being bound there?  With pcase, the binding would be 
explicit, and the accompanying `guard' expression would have a clear 
place in lexical scope, so there would be no doubt about where the 
arguments were bound.  With cond*, would the binding apply to the first 
argument symbol or a later one?  If the goal is to avoid implicit rather 
than explicit behavior, that seems contrary to the goal.

For these reasons, this seems more confusing to me than pcase, not less.

Sincerely,
Adam

0: 
https://git.savannah.gnu.org/cgit/emacs.git/tree/lisp/emacs-lisp/byte-opt.el?id=75fd7550ed6cede6c9e8224f1f2d62637c43fdd4#n1459

1: Perhaps we could recommend a minor change to pcase that might improve 
understanding: a `bind' keyword could be used to explicitly bind 
variables, rather than only having the implied binding from the `and' 
keyword (since `let' already has a different purpose in pcase).  So the 
example from earlier could look like:

   `(,head ,bindings . ,(or '() `(,(and (bind const) (guard 
(macroexp-const-p const))))))



^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: Instead of pcase
  2023-12-12  3:43                                   ` Richard Stallman
                                                       ` (3 preceding siblings ...)
  2023-12-13  1:32                                     ` Adam Porter
@ 2023-12-13  4:58                                     ` Richard Stallman
  4 siblings, 0 replies; 342+ messages in thread
From: Richard Stallman @ 2023-12-13  4:58 UTC (permalink / raw)
  To: michael_heerdegen; +Cc: emacs-devel

[[[ To any NSA and FBI agents reading my email: please consider    ]]]
[[[ whether defending the US Constitution against all enemies,     ]]]
[[[ foreign or domestic, requires you to follow Snowden's example. ]]]

I was compelled to copy pcase's `_' meaning "match anything" because I
could not see a way to do this with anything less arbitrary.
If anyone sees a cleaner way to do this, please tell me.

Here is the current definition of patterns for use in cond*.


**Possible types of patterns for :match and the match-... functions**

CONSTANT: nil, t, a keyword, a quoted constant, fixed parts of a backquote

  This matches any value equal to CONSTANT.
_

  _ means to match any value and not store it anywhere.

VARIABLE: a symbol

  A symbol means to match any value and set VARIABLE to it.

A quoted cons cell

  The car and the cdr are subpattenrs.  The cons cell pattern
  matches any cons cell whose car and cdr match those two subpatterns.
  How nil as a cdr matches is controlled by the match-nil flag.

  When the nil-match-all flag is false, nil as a cdr matches
  only nil itself.

  When the nil-match-all flag is true, nil as a cdr matches
  any object and ignores that object.

  The nil-match-all flag is false by default.  The `cdr' pattern maks
  it false within its its subpattern, and the `cdr-safe' pattern makes
  it true forwithin its its subpattern.

(cdr-safe QUOTED-CONS-CELL)

  This pattern is equivalent to QUOTED-CONS-CELL by itself
  except that it makes the nil-match-all flag true within it.

     (cdr-safe `(a b))  matches (a b), (a b c), (a b . d), etc.

(cdr QUOTED-CONS-CELL)

  This pattern is equivalent to QUOTED-CONS-CELL by itself
  except that it makes the nil-match-all flag false within it.

     (cdr `(a b))  matches only (a b).

Constrained variable: (TESTFN VARIABLE OTHER-ARGS...)

  This matches any value VALUE provided (TESTFN VALUE OTHER-ARGS...)
  evaluates to true.  If so, it sets VARIABLE to VALUE.

     (symbolp sym)    Match any symbol, store it in `sym'.
     (> num-foos 1)   Match any thing greater than 1, store it in `num-foos'.

  When matching to bind variables, this pattern unconditionally binds
  VARIABLE whether it matches or not.

  `quote', `constrain' and `or' cannot be used as TESTFN.

  Constrained variable constructs can be nested.

  For example,

    (< (numberp num-foos) 1)  Match any number > 1,  store it in mum-foos.

General constrained variable: (constrain VAR EXPRESSION)

  This general constrained variable pattern binds VAR to the
  value being matched against, only for evaluating EXPRESSION.
  If the result is non-nil, the match succeeds
  and sets VAR to the value.

  For instance,

    (constrain x (and (> x 0) (< x 100)))

Alternatives: (or SUBPATTERNS...)

  This tries to match each of the SUBPATTERNS in order until one matches.
  If the pattern is being used to bind variables, it binds all the variables
  specified in any of SUBPATTERNS

-- 
Dr Richard Stallman (https://stallman.org)
Chief GNUisance of the GNU Project (https://gnu.org)
Founder, Free Software Foundation (https://fsf.org)
Internet Hall-of-Famer (https://internethalloffame.org)





^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: Instead of pcase
  2023-12-13  1:32                                     ` Adam Porter
@ 2023-12-14  3:23                                       ` Richard Stallman
  2023-12-16  4:23                                       ` Richard Stallman
                                                         ` (2 subsequent siblings)
  3 siblings, 0 replies; 342+ messages in thread
From: Richard Stallman @ 2023-12-14  3:23 UTC (permalink / raw)
  To: Adam Porter; +Cc: emacs-devel

[[[ To any NSA and FBI agents reading my email: please consider    ]]]
[[[ whether defending the US Constitution against all enemies,     ]]]
[[[ foreign or domestic, requires you to follow Snowden's example. ]]]

  > One also wonders what it would look like if such a cond* form had 
  > multiple, overlapping fall-through bindings of the same variables--that 
  > would seem to be necessary in some cases, and would likely be confusing.

Why would someone write duplicate drop-through clauses
in a single cond* form?

It looks like you think there is some reason, but I can't guess it.

-- 
Dr Richard Stallman (https://stallman.org)
Chief GNUisance of the GNU Project (https://gnu.org)
Founder, Free Software Foundation (https://fsf.org)
Internet Hall-of-Famer (https://internethalloffame.org)





^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: [External] : Re: Instead of pcase
  2023-12-12 15:18                                     ` [External] : " Drew Adams
@ 2023-12-14  3:24                                       ` Richard Stallman
  2023-12-14 16:52                                         ` Drew Adams
  0 siblings, 1 reply; 342+ messages in thread
From: Richard Stallman @ 2023-12-14  3:24 UTC (permalink / raw)
  To: Drew Adams; +Cc: michael_heerdegen, emacs-devel

[[[ To any NSA and FBI agents reading my email: please consider    ]]]
[[[ whether defending the US Constitution against all enemies,     ]]]
[[[ foreign or domestic, requires you to follow Snowden's example. ]]]

  > It might be clearer if clauses that can end
  > the `cond*' are easily distinguished from
  > those that always continue on to the next
  > clause - their return value doesn't matter to
  > the control flow (e.g., they just match/bind).

That is rather abstract, and I am not sure what idea you are
proposing.  If you send a specific proposal I can think about it.

  > Or is the former always the case if a clause
  > contains two successive sexps?

I am not sure what "the former" refers to.  Could you please state
your point in a way that takes less work to understand?

p
-- 
Dr Richard Stallman (https://stallman.org)
Chief GNUisance of the GNU Project (https://gnu.org)
Founder, Free Software Foundation (https://fsf.org)
Internet Hall-of-Famer (https://internethalloffame.org)





^ permalink raw reply	[flat|nested] 342+ messages in thread

* RE: [External] : Re: Instead of pcase
  2023-12-14  3:24                                       ` Richard Stallman
@ 2023-12-14 16:52                                         ` Drew Adams
  2023-12-16  4:24                                           ` Richard Stallman
  0 siblings, 1 reply; 342+ messages in thread
From: Drew Adams @ 2023-12-14 16:52 UTC (permalink / raw)
  To: rms@gnu.org; +Cc: michael_heerdegen@web.de, emacs-devel@gnu.org

>   > It might be clearer if clauses that can end
>   > the `cond*' are easily distinguished from
>   > those that always continue on to the next
>   > clause - their return value doesn't matter to
>   > the control flow (e.g., they just match/bind).
> 
> That is rather abstract, and I am not sure what idea you are
> proposing.  If you send a specific proposal I can think about it.

I'm not proposing anything there.  I'm saying that
your introduction of fall-through clauses that can't
end the cond* (and thus provide its value) introduces
complexity and can cause confusion.

In terms of a proposal: If you're going to allow
clauses that just "fall through" (e.g. only match &
bind), then (1) tell users how to easily recognize
them and (2) maybe even add something syntactic that
distinguishes them more easily.

>   > Or is the former always the case if a clause
>   > contains two successive sexps?
> 
> I am not sure what "the former" refers to.  Could you please state
> your point in a way that takes less work to understand?

"Former" here refers to clauses that can end the
cond*.  The "latter" kind of clauses cannot; they
always "fall through" (whether or not they perform
some action, such as matching/binding).

What distinguishes a clause that can end the cond*?
How can you tell immediately, independent of what
some sexp is/does, whether the clause it's in can
possibly end the cond* and provide its return value?

That's my question.

I guessed that this possibility is the case whenever
a clause contains only _one sexp_.  If so, that's OK,
but then say that.  And even so, it might be good to
have some clearer indication, to distinguish such
clauses.

Others have already spoken to the oddity of clauses
that can "fall through", that can't, themselves, end
the cond*.  Make it clearer when this is the case -
especially for a construct whose name is so similar
to cond's.  In a traditional `cond' each clause can
potentially end the cond and provide its return value.

^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: Instead of pcase
  2023-12-13  1:32                                     ` Adam Porter
  2023-12-14  3:23                                       ` Richard Stallman
@ 2023-12-16  4:23                                       ` Richard Stallman
  2023-12-18  4:09                                         ` cond* Richard Stallman
  2023-12-18  4:09                                         ` cond* Richard Stallman
  2023-12-16  4:23                                       ` Instead of pcase Richard Stallman
  2023-12-16  4:23                                       ` Richard Stallman
  3 siblings, 2 replies; 342+ messages in thread
From: Richard Stallman @ 2023-12-16  4:23 UTC (permalink / raw)
  To: Adam Porter; +Cc: emacs-devel

[[[ To any NSA and FBI agents reading my email: please consider    ]]]
[[[ whether defending the US Constitution against all enemies,     ]]]
[[[ foreign or domestic, requires you to follow Snowden's example. ]]]

  > > (defun byte-optimize-letX (form)
  > >   (cond*
  > >     ;; Bindings list is empty.
  > >     (:match (`(,_ () . ,body) form)
  > >      `(progn . ,body))

  > This is nearly identical to the equivalent pcase syntax, only adding 
  > `:match'.  Since pcase's (and I suppose cond*'s) purpose is pattern 
  > matching, this seems redundant and unnecessarily verbose.

That's right. pcase has only one kind of clause, and all clauses
match against one single value.  cond* is more powerful and therefore
it requires keywords to specify non-cond clauses.

  > >     ;; Decompose the form
  > >     (:match (`(,head ,bindings . ,body) form))

  > I suppose it is largely a matter of taste, but I strongly dislike 
  > fall-through clauses.  While it seems convenient here, as it allows the 
  > removal of either a redundancy (reiterating bindings in multiple 
  > clauses) or a level of nesting, its bindings are also implicit rather 
  > than explicit, as the scope of the binding form is not enclosed by 
  > visible boundaries (i.e. parens).

These bindings run from the place they are made
to the closeparen at the end of the containing cond*.
I think those bounds are easy to see.

The use of a fall-through :match clause avoids the need to bind the
variables separately for each clause, and the chance that they may
differ (not incorrectly, but perhaps confusingly) in different
clauses.

However, it shares with pcase the design idea that variables
to be bound by pattern matching are buried inside of a pattern,
not centralized in one list that makes them easy to find.

If people generally find that confusing, perhaps it would be good
to change the fall-through :match clause so that the variables to be bound
_must_ be listed "redundantly" in a previous :bind clause.
This would make the code a little longer
but make it easier to read.

  > >     ;; Body is empty or just contains a constant.
  > >     (:match ((or `() `(,(macroexp-const-p const))) body)

  > This seems even more confusing to me.  The equivalent pcase form is:

  >    `(,head ,bindings . ,(or '() `(,(and const (pred macroexp-const-p)))))

I think the cond* method is simpler.  (macroexp-const-p const) is both
simpler and more natural than (and const (pred macroexp-const-p)).

-- 
Dr Richard Stallman (https://stallman.org)
Chief GNUisance of the GNU Project (https://gnu.org)
Founder, Free Software Foundation (https://fsf.org)
Internet Hall-of-Famer (https://internethalloffame.org)





^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: Instead of pcase
  2023-12-13  1:32                                     ` Adam Porter
  2023-12-14  3:23                                       ` Richard Stallman
  2023-12-16  4:23                                       ` Richard Stallman
@ 2023-12-16  4:23                                       ` Richard Stallman
  2023-12-16  4:23                                       ` Richard Stallman
  3 siblings, 0 replies; 342+ messages in thread
From: Richard Stallman @ 2023-12-16  4:23 UTC (permalink / raw)
  To: Adam Porter; +Cc: emacs-devel

[[[ To any NSA and FBI agents reading my email: please consider    ]]]
[[[ whether defending the US Constitution against all enemies,     ]]]
[[[ foreign or domestic, requires you to follow Snowden's example. ]]]

My aim in cond* is to include the convenient aspects of pcase without
its rigidity of framework, which requires the programmer to squeeze
things into it that don't easily fit.  That rigidity is the fact that
if you want to put one clause into a pcase which can't be written in
pcase language, you have to redesign that whole pcase.

I suspect that that rigidity creates pressure to extend pcase language
to be universal -- so that there can't ever be one clause that you
"can't express in pcase language."

cond* avoids that problem completely.  It lets you use pcase-like
patterns where they are convenient, interspersed with Lisp code where
that is convenient.

The cond* pattern specification is a little more complex than it was
in the first version, but it is still far simpler than the pcase
language.

As far as I know, it needs no further extension.  I looked at the 
pcase examples that were suggested, and they don't need any further
extension.

The `cdr' and `cdr-safe' feature is not strictly necessary, but the
lack of this feature in pcase leads to filling up many patterns with
lots of `_' subpatterns.  I think this feature is an improvement, but
omitting it would only reintroduce the added complexity of those `_'
subpatterns.

Can anyone show me more pcase examples I should study, which you think
show cases that call for adding any more pattern features to cond*?

-- 
Dr Richard Stallman (https://stallman.org)
Chief GNUisance of the GNU Project (https://gnu.org)
Founder, Free Software Foundation (https://fsf.org)
Internet Hall-of-Famer (https://internethalloffame.org)





^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: Instead of pcase
  2023-12-13  1:32                                     ` Adam Porter
                                                         ` (2 preceding siblings ...)
  2023-12-16  4:23                                       ` Instead of pcase Richard Stallman
@ 2023-12-16  4:23                                       ` Richard Stallman
  2023-12-16  6:57                                         ` Adam Porter
  3 siblings, 1 reply; 342+ messages in thread
From: Richard Stallman @ 2023-12-16  4:23 UTC (permalink / raw)
  To: Adam Porter; +Cc: emacs-devel

[[[ To any NSA and FBI agents reading my email: please consider    ]]]
[[[ whether defending the US Constitution against all enemies,     ]]]
[[[ foreign or domestic, requires you to follow Snowden's example. ]]]

  > As well, what if the user needed to pass an already-bound argument in 
  > addition to the one being bound there?  With pcase, the binding would be 
  > explicit, and the accompanying `guard' expression would have a clear 
  > place in lexical scope, so there would be no doubt about where the 
  > arguments were bound.

I am having trouble grasping the abstract description.  Would you like
to show an example of the putative problem that you are concerned
about?  I might understand it then.


-- 
Dr Richard Stallman (https://stallman.org)
Chief GNUisance of the GNU Project (https://gnu.org)
Founder, Free Software Foundation (https://fsf.org)
Internet Hall-of-Famer (https://internethalloffame.org)





^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: [External] : Re: Instead of pcase
  2023-12-14 16:52                                         ` Drew Adams
@ 2023-12-16  4:24                                           ` Richard Stallman
  2023-12-16  5:04                                             ` Drew Adams
  0 siblings, 1 reply; 342+ messages in thread
From: Richard Stallman @ 2023-12-16  4:24 UTC (permalink / raw)
  To: Drew Adams; +Cc: michael_heerdegen, emacs-devel

[[[ To any NSA and FBI agents reading my email: please consider    ]]]
[[[ whether defending the US Constitution against all enemies,     ]]]
[[[ foreign or domestic, requires you to follow Snowden's example. ]]]

  > In terms of a proposal: If you're going to allow
  > clauses that just "fall through" (e.g. only match &
  > bind), then (1) tell users how to easily recognize
  > them

The file says this.

    In this version, each clause exits if it contains more than one
    element (after the possible keyword), and falls through otherwise.

I think that is clear and simple.  I don't know if I have posted that
part.

         and (2) maybe even add something syntactic that
  > distinguishes them more easily.

There are many ways to do that.  Which would you propose?

-- 
Dr Richard Stallman (https://stallman.org)
Chief GNUisance of the GNU Project (https://gnu.org)
Founder, Free Software Foundation (https://fsf.org)
Internet Hall-of-Famer (https://internethalloffame.org)





^ permalink raw reply	[flat|nested] 342+ messages in thread

* RE: [External] : Re: Instead of pcase
  2023-12-16  4:24                                           ` Richard Stallman
@ 2023-12-16  5:04                                             ` Drew Adams
  2023-12-16 18:30                                               ` Bob Rogers
  0 siblings, 1 reply; 342+ messages in thread
From: Drew Adams @ 2023-12-16  5:04 UTC (permalink / raw)
  To: rms@gnu.org; +Cc: michael_heerdegen@web.de, emacs-devel@gnu.org

>   > In terms of a proposal: If you're going to allow
>   > clauses that just "fall through" (e.g. only match &
>   > bind), then (1) tell users how to easily recognize
>   > them
> 
> The file says this.
> 
>     In this version, each clause exits if it contains more than one
>     element (after the possible keyword), and falls through otherwise.
> 
> I think that is clear and simple.  I don't know if I have posted that
> part.

That's what I guessed.  Stating it explicitly gives
users something quick to look for, to more easily
parse things.

>   > and (2) maybe even add something syntactic that
>   > distinguishes them more easily.
> 
> There are many ways to do that.  Which would you propose?

I don't have a concrete suggestion, but I do think
_some_ syntactic indication would help, as opposed
to discerning whether there's only one sexp.  (Not
that that's hard to do, but it that difference
doesn't "saute aux yeux".)

^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: Instead of pcase
  2023-12-16  4:23                                       ` Richard Stallman
@ 2023-12-16  6:57                                         ` Adam Porter
  2023-12-20  3:28                                           ` Richard Stallman
  0 siblings, 1 reply; 342+ messages in thread
From: Adam Porter @ 2023-12-16  6:57 UTC (permalink / raw)
  To: rms; +Cc: emacs-devel

Hello Richard,

On 12/15/23 22:23, Richard Stallman wrote:
>    > As well, what if the user needed to pass an already-bound argument in
>    > addition to the one being bound there?  With pcase, the binding would be
>    > explicit, and the accompanying `guard' expression would have a clear
>    > place in lexical scope, so there would be no doubt about where the
>    > arguments were bound.
> 
> I am having trouble grasping the abstract description.  Would you like
> to show an example of the putative problem that you are concerned
> about?  I might understand it then.

Here are some examples I put together that demonstrate, IMHO, that 
pcase's binding forms are more explicit and less confusing.

;; In the match, will "bar" be called with "CONST" or "FOO" as the
;; first argument?
(cl-labels ((bar (one two)
               t))
   (let ((foo 'FOO)
         (const 'CONST)
         (body '(CONST FOO)))
     (cond* (:match ((or `()
                         `(,(bar foo const)))
                     body)))))

;; In the match, will "bar" be called with "CONST" or "FOO" as the
;; first argument?
(cl-labels ((bar (one two)
               t))
   (let ((foo 'FOO)
         (const 'CONST)
         (body '(FOO CONST)))
     (cond* (:match ((or `()
                         `(,(bar const foo)))
                     body)))))

;; In the match, will "bar" be called with "FOO" or "B" as the second
;; argument?
(cl-labels ((bar (one two)
               t))
   (let ((foo 'FOO)
         (body '(A B)))
     (cond* (:match ((or `()
                         `(,(bar const foo)))
                     body)))))

;; pcase's bindings are more explicit and less confusing:
(cl-labels ((bar (one two)
               t))
   (let ((foo 'FOO)
         (const 'CONST)
         (body '(A B)))
     (pcase body
       ((or `()
            (and `(,const ,foo) ; Explicitly binds within scope of clause.
                 (guard (bar const foo)))) ; Binding of "foo" clearly 
shadows that of the LET form.
        (format "CONST:%S  FOO:%S" const foo))
       (_ "No match"))))
;; "CONST:A  FOO:B"



^ permalink raw reply	[flat|nested] 342+ messages in thread

* RE: [External] : Re: Instead of pcase
  2023-12-16  5:04                                             ` Drew Adams
@ 2023-12-16 18:30                                               ` Bob Rogers
  2023-12-18  4:13                                                 ` Richard Stallman
  0 siblings, 1 reply; 342+ messages in thread
From: Bob Rogers @ 2023-12-16 18:30 UTC (permalink / raw)
  To: Drew Adams; +Cc: rms@gnu.org, michael_heerdegen@web.de, emacs-devel@gnu.org

   From: Drew Adams <drew.adams@oracle.com>
   Date: Sat, 16 Dec 2023 05:04:43 +0000

[re cond* fall-through behavior:]

   >   > and (2) maybe even add something syntactic that
   >   > distinguishes them more easily.
   > 
   > There are many ways to do that.  Which would you propose?

   I don't have a concrete suggestion, but I do think
   _some_ syntactic indication would help, as opposed
   to discerning whether there's only one sexp.  (Not
   that that's hard to do, but it that difference
   doesn't "saute aux yeux".)

Suppose clauses only fall through if the last form is the literal symbol
:fall-through ?  That is wordier and perhaps less elegant, but it would
make cond* more consistent with cond, and make the fall-through behavior
less apt to surprise.  (And apologies if this turns out to be infeasible
due to some other constraint; I've only been half following this
thread.)

					-- Bob Rogers
					   http://www.rgrjr.com/



^ permalink raw reply	[flat|nested] 342+ messages in thread

* cond*
  2023-12-16  4:23                                       ` Richard Stallman
@ 2023-12-18  4:09                                         ` Richard Stallman
  2023-12-18 10:08                                           ` cond* João Távora
  2023-12-19  3:49                                           ` cond* Richard Stallman
  2023-12-18  4:09                                         ` cond* Richard Stallman
  1 sibling, 2 replies; 342+ messages in thread
From: Richard Stallman @ 2023-12-18  4:09 UTC (permalink / raw)
  To: emacs-devel

[[[ To any NSA and FBI agents reading my email: please consider    ]]]
[[[ whether defending the US Constitution against all enemies,     ]]]
[[[ foreign or domestic, requires you to follow Snowden's example. ]]]

I've made cond*'s syntax more Lispy by changing
   (:match (PATTERN DATA)

to

   ((match* PATTERN DATA)

and likewise 

   (:bind VARLIST

to

   ((bind* VARLIST...)

This means that cond* no longer uses keywords itself.
This simplifies the criterion for a fall-through clause:
it has one exactly element.

The proposed macros `match' and `match-bind' are not necessary
because you can use

   (cond* ((match* PATTERN DATA) t))

and

   (cond* ((match* PATTERN DATA) BODY...))

which are hardly more complex to use.  So I have eliminated
those macros from the proposal.

I've tentatively added a new kind of clause,

   ((match-set* PATTERN DATA)

which sets pattern variables without binding them.
That can be used instead of the previously proposed macro, `match-set'.

But I am not sure whether this feature is really worth its added complexity.
Maybe in the end it should be omitted.



Each clause exits if it contains more than one
element, and falls through otherwise.

  (cond* 
       ;; Same as a clause in `cond',
       (CONDITION
        DO-THIS-IF-TRUE-THEN-EXIT...)

       ;; Execute FORM and ignore its value.
       (FORM)

       ;; Variables to bind, as in let*, around the rest
       ;; of the cond*.
       ((bind* (x foobar) y z (foo 5) a))
       ;; Bindings continue in effect for the whole cond* construct.

       ;; Bind variables for the clause, as in let*.
       ((bind* (foo 5) (condition (hack-it foo)))
        ;; condition is that the last variable bound be non-nil.
        BODY...)
       ;; Bindings no longer in effect.

       ;; Extracts substructure and binds variables for the clause.
       ((match* `(expt ,foo ,bar) x)
        DO-THIS-IF-IT-MATCHED-THEN-EXIT...)
       ;; Bindings no longer in effect.

       ;; Extracts substructure and binds variables
       ;; for the rest of the cond*.
       ;; Like above but always falls thru to next clause.
       ;; All the variables mentioned in the pattern
       ;; are bound whether match succeeds or not.
       ;; If a value can be determined from an incomplete match,
       ;; the variable gets that value.
       ((match* `(expt ,foo ,bar) x))
       ;; Bindings continue in effect.

       ;; Another example of fall-through match* clause.
       ;; All the variables mentioned in the pattern
       ;; are bound in all cases.
       ((match* (or `() `(,macroexp-const-p const)) body)

;; The `match-set*' is a tentative proposal.  It may not be worth including.
       ;; Extracts substructure and sets variables if match succeeds
       ((match-set* `(expt ,foo ,bar) x)
        DO-THIS-IF-IT-MATCHED-THEN-EXIT...)

       ;; Extracts substructure and sets variables without binding them.
       ;; Always falls thru to next clause.
       ((match-set* `(expt ,foo ,bar) x))
       )

To execute several expressions and not exit, use this:

       ((progn DO-THIS-UNCONDITIONALLY-AND-DONT-STOP...)

To test a condition and return its value if non-nil, use this:

       ((bind* (value CONDITION))
        value)

That has a small fixed amount of extra complexity compared with a
one-element cond clause, but given that those are not very common, this
is a small price to pay.
\f
**Possible types of patterns for match*.

CONSTANT: nil, t, a keyword, a quoted constant other than a cons cell,
          fixed parts of a backquote.

  This matches any value equal to CONSTANT.

_

  _ means to match any value and not store it anywhere.

VARIABLE: a symbol

  A symbol means to match any value and set VARIABLE to it.

A quoted cons cell

  The car and the cdr are subpattenrs.  The cons cell pattern
  matches any cons cell whose car and cdr match those two subpatterns.
  How nil as a cdr matches is controlled by the match-nil flag.

  When the nil-match-all flag is false, nil as a cdr matches
  only nil itself.

  When the nil-match-all flag is true, nil as a cdr matches
  any object and ignores that object.

  The nil-match-all flag is false by default.  The `cdr' pattern maks
  it false within its its subpattern, and the `cdr-safe' pattern makes
  it true forwithin its its subpattern.

(cdr-safe QUOTED-CONS-CELL)

  This pattern is equivalent to QUOTED-CONS-CELL by itself
  except that it makes the nil-match-all flag true within it.

     (cdr-safe `(a b))  matches (a b), (a b c), (a b . d), etc.

(cdr QUOTED-CONS-CELL)

  This pattern is equivalent to QUOTED-CONS-CELL by itself
  except that it makes the nil-match-all flag false within it.

     (cdr `(a b))  matches only (a b).

Constrained variable: (TESTFN VARIABLE OTHER-ARGS...)

  This matches any value VALUE provided (TESTFN VALUE OTHER-ARGS...)
  evaluates to true.  If so, it sets VARIABLE to VALUE.

     (symbolp sym)    Match any symbol, store it in `sym'.
     (> num-foos 1)   Match any thing greater than 1, store it in `num-foos'.

  When matching to bind variables, this pattern unconditionally binds
  VARIABLE whether it matches or not.

  `quote', `constrain' and `or' cannot be used as TESTFN.

  Constrained variable constructs can be nested.

  For example,

    (< (numberp num-foos) 1)  Match any number > 1,  store it in mum-foos.

General constrained variable: (constrain VAR EXPRESSION)

  This general constrained variable pattern binds VAR to the
  value being matched against, only for evaluating EXPRESSION.
  If the result is non-nil, the match succeeds
  and sets VAR to the value.

  For instance,

    (constrain x (and (> x 0) (< x 100)))

Alternatives: (or SUBPATTERNS...)

  This tries to match each of the SUBPATTERNS in order until one matches.
  If the pattern is being used to bind variables, it binds all the variables
  specified in any of SUBPATTERNS

-- 
Dr Richard Stallman (https://stallman.org)
Chief GNUisance of the GNU Project (https://gnu.org)
Founder, Free Software Foundation (https://fsf.org)
Internet Hall-of-Famer (https://internethalloffame.org)





^ permalink raw reply	[flat|nested] 342+ messages in thread

* cond*
  2023-12-16  4:23                                       ` Richard Stallman
  2023-12-18  4:09                                         ` cond* Richard Stallman
@ 2023-12-18  4:09                                         ` Richard Stallman
  2023-12-18  5:41                                           ` cond* Adam Porter
  1 sibling, 1 reply; 342+ messages in thread
From: Richard Stallman @ 2023-12-18  4:09 UTC (permalink / raw)
  To: emacs-devel

[[[ To any NSA and FBI agents reading my email: please consider    ]]]
[[[ whether defending the US Constitution against all enemies,     ]]]
[[[ foreign or domestic, requires you to follow Snowden's example. ]]]

To finish the design of cond*, we need to find what features
needed to be added so that it is rare to encounter a pcase
that can't be replaced cleanly.    Would people please tell me
about possible examples?


-- 
Dr Richard Stallman (https://stallman.org)
Chief GNUisance of the GNU Project (https://gnu.org)
Founder, Free Software Foundation (https://fsf.org)
Internet Hall-of-Famer (https://internethalloffame.org)





^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: [External] : Re: Instead of pcase
  2023-12-16 18:30                                               ` Bob Rogers
@ 2023-12-18  4:13                                                 ` Richard Stallman
  0 siblings, 0 replies; 342+ messages in thread
From: Richard Stallman @ 2023-12-18  4:13 UTC (permalink / raw)
  To: Bob Rogers; +Cc: emacs-devel

[[[ To any NSA and FBI agents reading my email: please consider    ]]]
[[[ whether defending the US Constitution against all enemies,     ]]]
[[[ foreign or domestic, requires you to follow Snowden's example. ]]]

  > Suppose clauses only fall through if the last form is the literal symbol
  > :fall-through ?

I'm not absolutely against it, but I think people will get used to
fall-throgh clauses based on having one element.  I'd like people to
try to do that, so we can see whether people do become used to it.

-- 
Dr Richard Stallman (https://stallman.org)
Chief GNUisance of the GNU Project (https://gnu.org)
Founder, Free Software Foundation (https://fsf.org)
Internet Hall-of-Famer (https://internethalloffame.org)





^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: cond*
  2023-12-18  4:09                                         ` cond* Richard Stallman
@ 2023-12-18  5:41                                           ` Adam Porter
  2023-12-21  4:20                                             ` cond* Richard Stallman
  0 siblings, 1 reply; 342+ messages in thread
From: Adam Porter @ 2023-12-18  5:41 UTC (permalink / raw)
  To: rms; +Cc: emacs-devel

> To finish the design of cond*, we need to find what features
> needed to be added so that it is rare to encounter a pcase
> that can't be replaced cleanly.    Would people please tell me
> about possible examples?

Well, one of the most common things I do with pcase is to destructure 
alists, plists, and structs, often nested at multiple levels.  For example:

(defun ement-ignore-user (user-id session &optional unignore-p)
   "Ignore USER-ID on SESSION.
If UNIGNORE-P (interactively, with prefix), un-ignore USER."
   (interactive (list (ement-complete-user-id)
                      (ement-complete-session)
                      current-prefix-arg))
   ;; NOTE: Destructures account-data slot of ement-session struct.
   (pcase-let* (((cl-struct ement-session account-data) session)
                ;; NOTE: Destructures alist nested in another alist and
                ;; binds to a variable of a different name than the key.
                ((map ('content (map ('ignored_users ignored-users))))
                 (cl-find "m.ignored_user_list" account-data
                          :key (lambda (event) (alist-get 'type event)) 
:test #'equal)))
     ...))

(defun ement--room-in-space-p (room space)
   "Return non-nil if ROOM is in SPACE on SESSION."
   ;; NOTE: Destructures slots in two structs to alternative variable
   ;; names, and destructures an alist key in each struct's `local'
   ;; slot to a variable of the same name.
   (pcase-let* (((cl-struct ement-room (id parent-id) (local (map 
children))) space)
                ((cl-struct ement-room (id child-id) (local (map 
parents))) room))
     ...))

No alternative to pcase that omitted these features could take its place 
for me.  In a large package like Ement.el, where function after function 
destructures similar objects in similar ways, the benefit of the 
consistency, conciseness, and flexibility offered by pcase can't be 
understated.

As well, pcase is easily extended with its built-in flexibility, e.g. 
how easily support was added for the cl-type based pattern.  It's a very 
well-designed system.

Then there are pcase-lambda, pcase-dolist, and pcase-setq, all of which 
use the same underlying facilities and patterns.  It's a coherent 
system: learning pcase opens up this world of useful forms.  I would not 
want to give up these powerful tools which make my programs better and 
my programming more enjoyable.



^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: cond*
  2023-12-18  4:09                                         ` cond* Richard Stallman
@ 2023-12-18 10:08                                           ` João Távora
  2023-12-21  4:20                                             ` cond* Richard Stallman
  2023-12-19  3:49                                           ` cond* Richard Stallman
  1 sibling, 1 reply; 342+ messages in thread
From: João Távora @ 2023-12-18 10:08 UTC (permalink / raw)
  To: rms; +Cc: emacs-devel

I think you definitely need to work on this part:

       ;; Extracts substructure and binds variables for the clause.
       ((match* `(expt ,foo ,bar) x)
        DO-THIS-IF-IT-MATCHED-THEN-EXIT...)
       ;; Bindings no longer in effect.

       ;; Extracts substructure and binds variables
       ;; for the rest of the cond*.
       ;; Like above but always falls thru to next clause.
       ;; All the variables mentioned in the pattern
       ;; are bound whether match succeeds or not.
       ;; If a value can be determined from an incomplete match,
       ;; the variable gets that value.
       ((match* `(expt ,foo ,bar) x))
       (t
            (something-that-depends-on FOO BAR) ; is this how to use it?
       )


am I going to use BAR and FOO in a form that is not contained
in any form that declares BAR and FOO as they are matched
and bound? This would seem to be an unhygienic macro, it's
asking for trouble and confuses the user's reading of byte
compiler output, which is currently very competent at
catching unused and potentially unbound variables (which
become especially evident when flymake-mode is used)

João



^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: cond*
  2023-12-18  4:09                                         ` cond* Richard Stallman
  2023-12-18 10:08                                           ` cond* João Távora
@ 2023-12-19  3:49                                           ` Richard Stallman
  2023-12-19 12:13                                             ` cond* João Távora
  2023-12-19 15:53                                             ` [External] : cond* Drew Adams
  1 sibling, 2 replies; 342+ messages in thread
From: Richard Stallman @ 2023-12-19  3:49 UTC (permalink / raw)
  To: emacs-devel

[[[ To any NSA and FBI agents reading my email: please consider    ]]]
[[[ whether defending the US Constitution against all enemies,     ]]]
[[[ foreign or domestic, requires you to follow Snowden's example. ]]]

It would be possible to indicate fall-through clauses
by making them start with t.  For instance,

  ((match* PATTERN DATA))

would become

  (t (match* PATTERN DATA))

With this change, whether a clause falls through would have nothing to
do with how many elements it has, only with whether its first element
is t.

Note that this change in rules would make no change
in the interpretation of a final clause that starts with t.

Please send me feedback about this proposed change.  If you like it,
if you dislike it, or if you think it makes little difference, I would
like to hear that from you.

-- 
Dr Richard Stallman (https://stallman.org)
Chief GNUisance of the GNU Project (https://gnu.org)
Founder, Free Software Foundation (https://fsf.org)
Internet Hall-of-Famer (https://internethalloffame.org)





^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: cond*
  2023-12-19  3:49                                           ` cond* Richard Stallman
@ 2023-12-19 12:13                                             ` João Távora
  2023-12-22  3:14                                               ` cond* Richard Stallman
  2023-12-19 15:53                                             ` [External] : cond* Drew Adams
  1 sibling, 1 reply; 342+ messages in thread
From: João Távora @ 2023-12-19 12:13 UTC (permalink / raw)
  To: rms; +Cc: emacs-devel

On Tue, Dec 19, 2023 at 3:49 AM Richard Stallman <rms@gnu.org> wrote:

> Please send me feedback about this proposed change.  If you like it,
> if you dislike it, or if you think it makes little difference, I would
> like to hear that from you.

If subsequent clauses can still access bindings in PATTERN,
then my previous doubts and criticism remain, and this change
makes little difference.



^ permalink raw reply	[flat|nested] 342+ messages in thread

* RE: [External] : Re: cond*
  2023-12-19  3:49                                           ` cond* Richard Stallman
  2023-12-19 12:13                                             ` cond* João Távora
@ 2023-12-19 15:53                                             ` Drew Adams
  2023-12-21  4:22                                               ` Richard Stallman
  2023-12-21  4:22                                               ` Richard Stallman
  1 sibling, 2 replies; 342+ messages in thread
From: Drew Adams @ 2023-12-19 15:53 UTC (permalink / raw)
  To: rms@gnu.org, emacs-devel@gnu.org

Apologies for not taking much time to check what
you've suggested in more detail.  If this reply
doesn't help, please just ignore it.

> It would be possible to indicate fall-through clauses
> by making them start with t.  For instance,
> 
>   ((match* PATTERN DATA))
> 
> would become
> 
>   (t (match* PATTERN DATA))
> 
> With this change, whether a clause falls through would have nothing to
> do with how many elements it has, only with whether its first element
> is t.

Noticing whether a clause has more than one sexp
isn't the best approach, I think, as I mentioned.

But adding `t' that way doesn't help either, IMO.
In fact, it can make things worse.

> Note that this change in rules would make no change
> in the interpretation of a final clause that starts with t.

Yes, and that's a source of confusion.  It looks
too much like a clause whose condition is always
true and whose _action_ (and the `cond*' return
value) is the effect (and the value) of that
`match*' sexp.

> Please send me feedback about this proposed change.  If you like it,
> if you dislike it, or if you think it makes little difference, I would
> like to hear that from you.

Thanks for trying to address the problem I raised
(to more easily distinguish no-action/return
clauses from action/return clauses).

Initially you had a no-action clause in this form:
(match* PATTERN DATA).  I actually (mis)thought
the initial form was what you _next_ proposed:
((match* PATTERN DATA)).

I also (mis)thought that action clauses, that is,
clauses whose return value can be the return value
of the `cond*', had a set of surrounding parens,
just as in `cond'.

And I was then thinking about suggesting that you
change a no-action clause to just what you in fact
had proposed initially (which I missed).  Then,
action clauses would continue to have surrounding
parens (just like a `cond' clause) and no-action
clauses would not - easier to see the difference.

A no-action clause affects all subsequent clauses.

So another suggestion was to be (and still could
be) to move a no-action sexp inside the parens
of the next action clause, instead of letting it
be a clause on its own.  That way, _all_ clauses
would be action clauses (i.e., could provide the
`cond*'s return value).  They just might have one
or more no-action sexps at their beginning.

E.g., instead of this:

(:match ...)          ; no-action sexp as a clause
(CONDITION . ACTIONS) ; action clause

You'd have this:

((:match ...) CONDITION . ACTIONS)

(Consecutive no-action sexps would be included in
the first action clause that follows them.)

I'd still suggest that, except that I have this
question: Is there perhaps such a case as having
a no-action sexp whose bindings are to be _local_
to the following action clause, i.e., they would
be undone for following clauses?

If that's the case, then a natural way to express
that would be to put the no-action sexp inside
the action clause that it affects.  IOW, the form
I suggested above for _all_ no-action sexps.

In that case, there'd be no way to distinguish a
no-action (e.g. binding) sexp that affects _all_
subsequent action clauses from one that's local to
just the next action clause.

So far, I don't think I've noticed any locality
of binding sexps - e.g., bindings that would be
undone for clauses following the immediately next
one.  If there won't be any clause-local no-action
sexps then the suggestion above might work.

To repeat the suggestion:

Require each clause to have a tail of
(CONDITION . ACTIONS):

  ([NO-ACTION-SEXP]* CONDITION . ACTIONS)

This means that a NO-ACTION-SEXP cannot appear on
its own, as a clause.  It's part of some clause
that has an action/return value.  Each clause can
end the `cond*' and provide its return value.

And, as previously, a NO-ACTION-SEXP affects the
clause it belongs to, _and_ subsequent ones.
(I.e., no possibility of a no-action sexp whose
effect is only local to a given clause.)

Again, apologies if I've missed something.  The
main point here is to not have no-action sexps
as clauses: the return value of any clause can
be the `cond*'s return value.

And again, by "no-action sexp" I just mean a
sexp that only matches/binds and whose result
can't possibly be the `cond*'s return value.

With this suggestion there's no "fall through".
Each no-action sexp belongs to some clause, and
each clause can provide the `cond*' return value.

Does this make sense?

^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: Instead of pcase
  2023-12-16  6:57                                         ` Adam Porter
@ 2023-12-20  3:28                                           ` Richard Stallman
  2023-12-20 10:52                                             ` Adam Porter
  0 siblings, 1 reply; 342+ messages in thread
From: Richard Stallman @ 2023-12-20  3:28 UTC (permalink / raw)
  To: Adam Porter; +Cc: emacs-devel

[[[ To any NSA and FBI agents reading my email: please consider    ]]]
[[[ whether defending the US Constitution against all enemies,     ]]]
[[[ foreign or domestic, requires you to follow Snowden's example. ]]]

I find these examples hard to understand because of the complexity
caused by the functions called `bar'.  I could not fully make sense of
the first one: I don't understand what you intend it to do, or what
you think it might do, or why it might do that.

It is indeed painfully complex, but I don't think that is the fault of
cond*.

Is it possible that the explanation of a constrained variable patterm
is not clear?

    Constrained variable: (TESTFN VARIABLE OTHER-ARGS...)

      This matches any value VALUE provided (TESTFN VALUE OTHER-ARGS...)
      evaluates to true.  If so, it sets VARIABLE to VALUE.

         (symbolp sym)    Match any symbol, store it in `sym'.
         (> num-foos 1)   Match any thing greater than 1, store it in `num-foos'.

Only the first argument to a TESTFN is a kind of subpattern.  The
OTHER-ARGS are handled are not patterns to match; they are expressions
to evaluate.  Their values are passed to TESTFN as in an ordinary
function call.

If TESTFN is your function `bar', it will then receive its arguments
in the usual way and do what it is defined to do.  It is used as a
predicate, so all that matters is whether its return value is non-nil.

The first parameter of `bar' will be data that this subpattern
may match or not.  The remaining parameters of `bar' will be the
results of evaluating OTHER-ARGS...


-- 
Dr Richard Stallman (https://stallman.org)
Chief GNUisance of the GNU Project (https://gnu.org)
Founder, Free Software Foundation (https://fsf.org)
Internet Hall-of-Famer (https://internethalloffame.org)





^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: Instead of pcase
  2023-12-20  3:28                                           ` Richard Stallman
@ 2023-12-20 10:52                                             ` Adam Porter
  2023-12-23  2:53                                               ` Richard Stallman
  2023-12-23  2:53                                               ` Richard Stallman
  0 siblings, 2 replies; 342+ messages in thread
From: Adam Porter @ 2023-12-20 10:52 UTC (permalink / raw)
  To: rms; +Cc: emacs-devel

On 12/19/23 21:28, Richard Stallman wrote:

> I find these examples hard to understand because of the complexity 
> caused by the functions called `bar'.

I did not add those functions to the example myself; I merely elaborated
on them to illustrate the problems I was pointing out.

> I could not fully make sense of the first one: I don't understand 
> what you intend it to do, or what you think it might do, or why it 
> might do that.

Yes, that is part of the point I am making: that the way COND* binds
variables and passes them to predicate forms is confusing.

> Is it possible that the explanation of a constrained variable patterm
> is not clear?
> 
> Constrained variable: (TESTFN VARIABLE OTHER-ARGS...)
> 
> This matches any value VALUE provided (TESTFN VALUE OTHER-ARGS...) 
> evaluates to true.  If so, it sets VARIABLE to VALUE.
> 
> (symbolp sym)    Match any symbol, store it in `sym'. (> num-foos 1) 
> Match any thing greater than 1, store it in `num-foos'.
> 
> Only the first argument to a TESTFN is a kind of subpattern.  The 
> OTHER-ARGS are handled are not patterns to match; they are 
> expressions to evaluate.  Their values are passed to TESTFN as in an 
> ordinary function call.

> The first parameter of `bar' will be data that this subpattern may 
> match or not.  The remaining parameters of `bar' will be the results 
> of evaluating OTHER-ARGS...

Yes, this is one of the problems I was trying to illustrate.  What if
the TESTFN needs VALUE as its second or later argument rather than as
the first?

Or what if TESTFN needs to receive multiple arguments bound from a
matched pattern?  What if TESTFN needs 3 arguments, and the middle one
is not from the matched pattern?  Or what if the middle one /is/ from
the matched pattern?

And what if there are naming conflicts among VARIABLE and OTHER-ARGS?
What if some of those symbols are already bound outside the COND* or in
another clause of it that falls through?

PCASE handles these situations in a better way by matching and binding 
separately and explicitly, providing the GUARD form to evaluate 
arbitrary expressions, which may or may not include variables bound in 
the pattern.



^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: cond*
  2023-12-18  5:41                                           ` cond* Adam Porter
@ 2023-12-21  4:20                                             ` Richard Stallman
  0 siblings, 0 replies; 342+ messages in thread
From: Richard Stallman @ 2023-12-21  4:20 UTC (permalink / raw)
  To: Adam Porter; +Cc: emacs-devel

[[[ To any NSA and FBI agents reading my email: please consider    ]]]
[[[ whether defending the US Constitution against all enemies,     ]]]
[[[ foreign or domestic, requires you to follow Snowden's example. ]]]

  > Well, one of the most common things I do with pcase is to destructure 
  > alists, plists, and structs, often nested at multiple levels.  For example:

These examples don't use pcase.  They use pcase-let*, which I am not
familiar with.

Although I now understand simple pcase usage, I can't relate what
I see in these examples to that.  I can't understand them at all.
If you explain to me what these examples do, and how they do it,
I might understand them enough to think about them.

As for pcase-let* in itself, its doc string is clear enough.  It uses
a series of bindings of the form (PATTERN VALUE).

We can do that naturally in cond* like this:

     (cond* (t (match* PATTERN VALUE))
            (t (match* PATTERN2 VALUE2))
            ...
            (t BODY...)))

so I think cond* avoids the need for a separate ...let* construct.


-- 
Dr Richard Stallman (https://stallman.org)
Chief GNUisance of the GNU Project (https://gnu.org)
Founder, Free Software Foundation (https://fsf.org)
Internet Hall-of-Famer (https://internethalloffame.org)





^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: cond*
  2023-12-18 10:08                                           ` cond* João Távora
@ 2023-12-21  4:20                                             ` Richard Stallman
  2023-12-21  9:50                                               ` cond* João Távora
  2023-12-21 14:10                                               ` cond* Ihor Radchenko
  0 siblings, 2 replies; 342+ messages in thread
From: Richard Stallman @ 2023-12-21  4:20 UTC (permalink / raw)
  To: João Távora; +Cc: emacs-devel

[[[ To any NSA and FBI agents reading my email: please consider    ]]]
[[[ whether defending the US Constitution against all enemies,     ]]]
[[[ foreign or domestic, requires you to follow Snowden's example. ]]]

  > am I going to use BAR and FOO

Are you talking about this?

   (cond*
       ((match* `(expt ,foo ,bar) x))
       (t
            (something-that-depends-on FOO BAR) ; is this how to use it?
       )

                                  in a form that is not contained
  > in any form that declares BAR and FOO as they are matched
  > and bound?

"Declares BAR and FOO as they are matched and bound"
is somewhat stramge usage of those words.  It is not
entirely clear what that means.  And I am not sure
what code you are talking about.

What you quoted is not an example of code.  It presents various sorts
of clauses that a cond* can contain, but not meant as one cond*
expression.  Those clauses do not try to work together validly.  So
you're judging them by a criterion they do not try to fit.

This tries to be a real example:

(defun byte-optimize-letX (form)
  (cond*
    ;; Bindings list is empty.
    ((match* `(,_ () . ,body) form)
     `(progn . ,body))

    ;; Decompose the form
    ((match* `(,head ,bindings . ,body) form))

    ;; Body is empty or just contains a constant.
    ((match* (or `() `(,(macroexp-const-p const))) body)
     ;; If the match succeeds, it always binds CONST.
     (if (eq head 'let)
         `(progn ,@(mapcar #'cadr bindings) ,const)
       `(,head ,(butlast bindings) ,(cadar (last bindings)) ,const)))

    ;; Body does nothing but return the last variable in bindings.
    ((let ((last-var (car-safe (car (last bindings)))))
       ;; Next line could be written using `match',
       ;; but the clarity of this is worth one cons.
       (and (symbolp last-var) (equal body (list last-var))))
     (if (eq head 'let)
         `(progn ,@(mapcar #'cadr bindings))
       `(,head ,(butlast bindings) ,(cadar (last bindings)))))

    (t form)))

head, bindings and body are bound in the cond* form, as specified
by the fall-through second clause, and they can be used
in the rest of the cond* clause.


-- 
Dr Richard Stallman (https://stallman.org)
Chief GNUisance of the GNU Project (https://gnu.org)
Founder, Free Software Foundation (https://fsf.org)
Internet Hall-of-Famer (https://internethalloffame.org)





^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: [External] : Re: cond*
  2023-12-19 15:53                                             ` [External] : cond* Drew Adams
@ 2023-12-21  4:22                                               ` Richard Stallman
  2023-12-21  4:22                                               ` Richard Stallman
  1 sibling, 0 replies; 342+ messages in thread
From: Richard Stallman @ 2023-12-21  4:22 UTC (permalink / raw)
  To: Drew Adams; +Cc: emacs-devel

[[[ To any NSA and FBI agents reading my email: please consider    ]]]
[[[ whether defending the US Constitution against all enemies,     ]]]
[[[ foreign or domestic, requires you to follow Snowden's example. ]]]

  > > Note that this change in rules would make no change
  > > in the interpretation of a final clause that starts with t.

  > Yes, and that's a source of confusion.

That makes no sense.  There is no possible confusion there.

Non-final clauses in cond never start with t,
so no one will expect tham to do anything other than
what this definition says.

So I think you are concerned about a non-problem.  Compared with all
the complexity people have to get used to in pcase, this is almost
nothing.

  > You'd have this:

  > ((:match ...) CONDITION . ACTIONS)

This syntax is not coherent and won't be an improvement.
It does not make sense to attach  a fall-through clause
to the following clause.  The fall-through clause's bindings
affect all the rest of the cond*, NOT just the following clause.

Getting used to a special meaning for t as the first element of a
cond* clause will be EASIER than getting used to a special meaning for
(:match ...) there.


So I will not accept that suggestion.  It creates a problem
where currentlly there is none.

I've decided no to use keywords in cond* any more.  You've put the
keywod :match that cond* previous used together with the syntax I've
adopted for the newer replacement, which is match*.  That combination
is not coherent.

-- 
Dr Richard Stallman (https://stallman.org)
Chief GNUisance of the GNU Project (https://gnu.org)
Founder, Free Software Foundation (https://fsf.org)
Internet Hall-of-Famer (https://internethalloffame.org)





^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: [External] : Re: cond*
  2023-12-19 15:53                                             ` [External] : cond* Drew Adams
  2023-12-21  4:22                                               ` Richard Stallman
@ 2023-12-21  4:22                                               ` Richard Stallman
  1 sibling, 0 replies; 342+ messages in thread
From: Richard Stallman @ 2023-12-21  4:22 UTC (permalink / raw)
  To: Drew Adams; +Cc: emacs-devel

[[[ To any NSA and FBI agents reading my email: please consider    ]]]
[[[ whether defending the US Constitution against all enemies,     ]]]
[[[ foreign or domestic, requires you to follow Snowden's example. ]]]

It would be easy to indicate a fall-through clause
with nil instead of t.  One advantage of nil is that
it is never used as the first element of a cond clause.

Or a keyword, such as :fall-thru, could do this job.

I prefer t or nil to a keyword, because they are more elegant.

-- 
Dr Richard Stallman (https://stallman.org)
Chief GNUisance of the GNU Project (https://gnu.org)
Founder, Free Software Foundation (https://fsf.org)
Internet Hall-of-Famer (https://internethalloffame.org)





^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: cond*
  2023-12-21  4:20                                             ` cond* Richard Stallman
@ 2023-12-21  9:50                                               ` João Távora
  2023-12-21 16:01                                                 ` [External] : cond* Drew Adams
  2023-12-24  3:57                                                 ` cond* Richard Stallman
  2023-12-21 14:10                                               ` cond* Ihor Radchenko
  1 sibling, 2 replies; 342+ messages in thread
From: João Távora @ 2023-12-21  9:50 UTC (permalink / raw)
  To: rms; +Cc: emacs-devel

On Thu, Dec 21, 2023 at 4:20 AM Richard Stallman <rms@gnu.org> wrote:

> Are you talking about this?
>
>    (cond*
>        ((match* `(expt ,foo ,bar) x))
>        (t
>             (something-that-depends-on FOO BAR) ; is this how to use it?
>        )

Yes.  It is very simple.  In Elisp or any Lisp I know, forms that
introduce bindings are also the containers of any forms that use
such bindings, most notable case being (let VARLIST BODY...)

This principle is not a cosmetic convention. It's essential
as it makes things like following the 'foo' in:

(dolist (foo '(1))
    (funcall (lambda (foo)
               (let ((foo 2))
                 (message "%" foo)))
             3))

easy, even to the beginner, because one just travels up the form
tree to a notable binding-introducing form.

A given match* form in a given use of your cond* doesn't have this
property. It introduces bindings that can be used by other forms
_outside_ it and this leads to ambiguity.  Adam noted this too.

> So you're judging them by a criterion they do not try to fit.

Well, I can't guess your intent, but I can tell you skipping this
criterion is a bad idea, IMO.

João



^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: cond*
  2023-12-21  4:20                                             ` cond* Richard Stallman
  2023-12-21  9:50                                               ` cond* João Távora
@ 2023-12-21 14:10                                               ` Ihor Radchenko
  2023-12-24  3:57                                                 ` cond* Richard Stallman
  1 sibling, 1 reply; 342+ messages in thread
From: Ihor Radchenko @ 2023-12-21 14:10 UTC (permalink / raw)
  To: rms; +Cc: João Távora, emacs-devel

Richard Stallman <rms@gnu.org> writes:

> ...
> This tries to be a real example:
>
> (defun byte-optimize-letX (form)
>   (cond*
> ...
>     ;; Decompose the form
>     ((match* `(,head ,bindings . ,body) form))
>
>     ;; Body is empty or just contains a constant.
>     ((match* (or `() `(,(macroexp-const-p const))) body)

This may be confusing. Consider

(let ((somenumber 2) (form '(10)))
(cond*
  ((match* `(,(> (+ somenumber form-car-value) 3))) form)
))

It is not clear how to mark actual variables and variables to-be-bound
inside ,(...) match* constructs.

-- 
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] 342+ messages in thread

* RE: [External] : Re: cond*
  2023-12-21  9:50                                               ` cond* João Távora
@ 2023-12-21 16:01                                                 ` Drew Adams
  2023-12-21 16:20                                                   ` João Távora
  2023-12-24  3:56                                                   ` Richard Stallman
  2023-12-24  3:57                                                 ` cond* Richard Stallman
  1 sibling, 2 replies; 342+ messages in thread
From: Drew Adams @ 2023-12-21 16:01 UTC (permalink / raw)
  To: João Távora, rms@gnu.org; +Cc: emacs-devel@gnu.org

> A given match* form in a given use of your cond* doesn't have this
> property. It introduces bindings that can be used by other forms
> _outside_ it and this leads to ambiguity.  Adam noted this too.

Maybe you meant Drew (Adams), not Adam (Porter).
In any case, yes, that's something I pointed out.

It's the reason I suggested putting all sexps
that only match/bind, i.e., sexps that can never
end the `cond*' and provide its value, inside a
clause that _can_ do that (i.e., a clause that's
not match/bind-only).

And to Richard's objection to that: Yes, it must
be made clear (e.g. in the doc) that a sexp that
only matches/binds applies to _everything_ that
follows it in the `cond*', not just to the one
clause in which it occurs.

And I asked the question (no response yet) of
whether there is ever any need/intention to
provide for match/bind-only sexps that are
_local_ to a given clause, i.e., their bindings
don't exist (are undone) outside that clause.

If there is such a need/intention, then how to
indicate that?  The obvious way would be the
syntax I suggested above (for non-local use):
just put that match/bind-only sexp inside the
clause to which it's local.  In that case, some
other syntax would be needed for the "global"
case (i.e., for a binding that applies to
subsequent clauses as well).

If not (no need for locals), then saying that a
binding applies to both the current clause and
subsequent clauses still makes sense. 

^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: [External] : Re: cond*
  2023-12-21 16:01                                                 ` [External] : cond* Drew Adams
@ 2023-12-21 16:20                                                   ` João Távora
  2023-12-24  3:56                                                   ` Richard Stallman
  1 sibling, 0 replies; 342+ messages in thread
From: João Távora @ 2023-12-21 16:20 UTC (permalink / raw)
  To: Drew Adams; +Cc: rms@gnu.org, emacs-devel@gnu.org

On Thu, Dec 21, 2023 at 4:01 PM Drew Adams <drew.adams@oracle.com> wrote:
>
> > A given match* form in a given use of your cond* doesn't have this
> > property. It introduces bindings that can be used by other forms
> > _outside_ it and this leads to ambiguity.  Adam noted this too.
>
> Maybe you meant Drew (Adams), not Adam (Porter).
> In any case, yes, that's something I pointed out.

I really meant Adam, as I _think_ he (also) pointed it out.
But if you also did, that's good!

João



^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: cond*
  2023-12-19 12:13                                             ` cond* João Távora
@ 2023-12-22  3:14                                               ` Richard Stallman
  2023-12-22  7:27                                                 ` cond* Philip Kaludercic
  0 siblings, 1 reply; 342+ messages in thread
From: Richard Stallman @ 2023-12-22  3:14 UTC (permalink / raw)
  To: emacs-devel

[[[ To any NSA and FBI agents reading my email: please consider    ]]]
[[[ whether defending the US Constitution against all enemies,     ]]]
[[[ foreign or domestic, requires you to follow Snowden's example. ]]]

Fall-through clauses are an important feature of cond* and a big
advance in flexibility.  Precisely how to indicate one is a detail,
and I've proposed three ways to design that:

* A clause with one element.
* A clause that starts with t.
* A clause that starts with nil.
* A keyword.

If you have preferences about that detail, please let me know.
I am also interested in other suggestions, but I will only accept
it if it is as natural and simple as those above.

-- 
Dr Richard Stallman (https://stallman.org)
Chief GNUisance of the GNU Project (https://gnu.org)
Founder, Free Software Foundation (https://fsf.org)
Internet Hall-of-Famer (https://internethalloffame.org)





^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: cond*
  2023-12-22  3:14                                               ` cond* Richard Stallman
@ 2023-12-22  7:27                                                 ` Philip Kaludercic
  2023-12-25  3:41                                                   ` cond* Richard Stallman
  0 siblings, 1 reply; 342+ messages in thread
From: Philip Kaludercic @ 2023-12-22  7:27 UTC (permalink / raw)
  To: Richard Stallman; +Cc: emacs-devel

Richard Stallman <rms@gnu.org> writes:

> [[[ To any NSA and FBI agents reading my email: please consider    ]]]
> [[[ whether defending the US Constitution against all enemies,     ]]]
> [[[ foreign or domestic, requires you to follow Snowden's example. ]]]
>
> Fall-through clauses are an important feature of cond* and a big
> advance in flexibility.  Precisely how to indicate one is a detail,
> and I've proposed three ways to design that:
>
> * A clause with one element.
> * A clause that starts with t.
> * A clause that starts with nil.
> * A keyword.
>
> If you have preferences about that detail, please let me know.
> I am also interested in other suggestions, but I will only accept
> it if it is as natural and simple as those above.

Have I missed something, or where is the source code for cond*.
Skimming through the messages, I don't quite understand how it is
supposed to work.



^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: Instead of pcase
  2023-12-20 10:52                                             ` Adam Porter
@ 2023-12-23  2:53                                               ` Richard Stallman
  2023-12-23  2:53                                               ` Richard Stallman
  1 sibling, 0 replies; 342+ messages in thread
From: Richard Stallman @ 2023-12-23  2:53 UTC (permalink / raw)
  To: Adam Porter; +Cc: emacs-devel

[[[ To any NSA and FBI agents reading my email: please consider    ]]]
[[[ whether defending the US Constitution against all enemies,     ]]]
[[[ foreign or domestic, requires you to follow Snowden's example. ]]]

  > > I could not fully make sense of the first one: I don't understand 
  > > what you intend it to do, or what you think it might do, or why it 
  > > might do that.

  > Yes, that is part of the point I am making: that the way COND* binds
  > variables and passes them to predicate forms is confusing.

For me, what is confusing is the rest of those examples,
such as the use of subroutines called `bar' which do various
things that you didn't explain.

If you tell me what you are trying to do in each case, I could
show you examples of how to do it in a simple way with cond*.

-- 
Dr Richard Stallman (https://stallman.org)
Chief GNUisance of the GNU Project (https://gnu.org)
Founder, Free Software Foundation (https://fsf.org)
Internet Hall-of-Famer (https://internethalloffame.org)





^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: Instead of pcase
  2023-12-20 10:52                                             ` Adam Porter
  2023-12-23  2:53                                               ` Richard Stallman
@ 2023-12-23  2:53                                               ` Richard Stallman
  2023-12-25 14:26                                                 ` Ihor Radchenko
  1 sibling, 1 reply; 342+ messages in thread
From: Richard Stallman @ 2023-12-23  2:53 UTC (permalink / raw)
  To: Adam Porter; +Cc: emacs-devel

[[[ To any NSA and FBI agents reading my email: please consider    ]]]
[[[ whether defending the US Constitution against all enemies,     ]]]
[[[ foreign or domestic, requires you to follow Snowden's example. ]]]

  > Or what if TESTFN needs to receive multiple arguments bound from a
  > matched pattern?  What if TESTFN needs 3 arguments, and the middle one
  > is not from the matched pattern?  Or what if the middle one /is/ from
  > the matched pattern?

Thank you.  I did not realize that my description was unclear in this way.
I've done a lot of rewriting; I hope this version is clearer.


Constrained variable: (PRED VARIABLE)  or, more generally,
                      (PRED VARIABLE OTHER-ARGS...)

  This matches any value VALUE that satisfies a specified constraint.
  PRED is a function to test the constraint.  It receives VALUE as an
  argument.  If PRED returns true, that means VALUE matches the
  constraint, so this pattern binds (or sets) VARIABLE to that value.
  For instance,

     (symbolp sym)   ; Match any symbol, bind `sym' to it.

  If you wish, you can specify additional arguments to pass to PRED.
  The OTHER-ARGS are not patterns to match, they are Lisp expressions
  to whose values specify the additional arguments to pass to PRED,
  following the first argument which is VALUE.  In effect, the call
  to PRED looks like this:
      (apply PRED VALUE (mapcar 'eval OTHER-ARGS))

  For example,
 
     (> num-foos 1)  ; Match any number greater than 1, bind `num-foos' to it.
     (> num-foos min-foos)  ; Match any number greater than MIN-FOOS,
                            ;  bind `num-foos' to it.

  When matching to bind variables, the presence of this kind of
  subpattern in the overall pattern to be matched unconditionally
  binds VARIABLE whether the subpattern matches or not.

  Constrained variable constructs can be nested

  For example,

    (< (integerp num-foos) 1)  ; Match any integer number > 1,
                               ;  bind `num-foos' to it.

  Advanced hack for experts: the OTHER-ARGS can refer to variables
  bound earlier in this pattern-matching operation.  For example,

  `(,(integerp smaller) ,(> (integerp bigger) smaller))
     ; Matches a list of two integers in which the second integer
     ; is larger than the first.

  (or `(,(integerp smaller) ,(> (integerp bigger) smaller))
      `(,(integerp bigger) ,(< (integerp smaller) bigger)))
     ; matches a ist of two integers and binds `bigger' to the bigger one
     ; and `smaller' to the smaller one.

  However, it might be cleaner to match the two integers regardless of
  their numberical ordering, then in Lisp code see which one is larger.

General constrained variable: (constrain VAR EXPRESSION)

  This general constrained variable pattern binds VAR to the
  value being matched against, tentatively, then evaluates EXPRESSION.
  If the result is true, the match succeeds and leaves VAR
  bound to that value.

  For instance,

    (constrain x (and (> x 0) (< x 100)))

  succeeds if the value being matched aainst is in the open interval (0, 100),
  and in that case it binds x to that value.

-- 
Dr Richard Stallman (https://stallman.org)
Chief GNUisance of the GNU Project (https://gnu.org)
Founder, Free Software Foundation (https://fsf.org)
Internet Hall-of-Famer (https://internethalloffame.org)





^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: [External] : Re: cond*
  2023-12-21 16:01                                                 ` [External] : cond* Drew Adams
  2023-12-21 16:20                                                   ` João Távora
@ 2023-12-24  3:56                                                   ` Richard Stallman
  1 sibling, 0 replies; 342+ messages in thread
From: Richard Stallman @ 2023-12-24  3:56 UTC (permalink / raw)
  To: Drew Adams; +Cc: joaotavora, emacs-devel

[[[ To any NSA and FBI agents reading my email: please consider    ]]]
[[[ whether defending the US Constitution against all enemies,     ]]]
[[[ foreign or domestic, requires you to follow Snowden's example. ]]]

  > And I asked the question (no response yet) of
  > whether there is ever any need/intention to
  > provide for match/bind-only sexps that are
  > _local_ to a given clause, i.e., their bindings
  > don't exist (are undone) outside that clause.

I saw that message, but I didn't notice that question then.  I saw
only a proposal for a syntax that would insert a non-exit clause
inside the following ordinary clause.  My reply was that that syntax
seemed unnatural for what the feature does.

Now I see you meant to propose a different feature, one which would
make bindings that apply only to the following clause.  Such a feature
could occasionally be useful, but not useful enough to justify adding
an additional feature.  It would not be an adequate replacement for
the non-exit clause feature.

I've chosen the term "non-exit clause" because that name states the
feature's overall effect, and its purpose.  "Falling through" is just
a part of the effect.
-- 
Dr Richard Stallman (https://stallman.org)
Chief GNUisance of the GNU Project (https://gnu.org)
Founder, Free Software Foundation (https://fsf.org)
Internet Hall-of-Famer (https://internethalloffame.org)





^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: cond*
  2023-12-21 14:10                                               ` cond* Ihor Radchenko
@ 2023-12-24  3:57                                                 ` Richard Stallman
  2023-12-25 14:14                                                   ` cond* Ihor Radchenko
  0 siblings, 1 reply; 342+ messages in thread
From: Richard Stallman @ 2023-12-24  3:57 UTC (permalink / raw)
  To: Ihor Radchenko; +Cc: joaotavora, emacs-devel

[[[ To any NSA and FBI agents reading my email: please consider    ]]]
[[[ whether defending the US Constitution against all enemies,     ]]]
[[[ foreign or domestic, requires you to follow Snowden's example. ]]]

  > This may be confusing. Consider

  > (let ((somenumber 2) (form '(10)))
  > (cond*
  >   ((match* `(,(> (+ somenumber form-car-value) 3))) form)
  > ))

This tries to use (> (+ somenumber form-car-value) 3) as a constrained
variable, but it is not valid as one.  In a constrained variable, the
first argument of the predicate function is supposed to be a pattern
to match.  It can't be an expression such as (+ somenumber
form-car-value).

Yesterday I rewrote the documentation of constrained variables and
sent that to the list.  Does that version make this clear?

-- 
Dr Richard Stallman (https://stallman.org)
Chief GNUisance of the GNU Project (https://gnu.org)
Founder, Free Software Foundation (https://fsf.org)
Internet Hall-of-Famer (https://internethalloffame.org)





^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: cond*
  2023-12-21  9:50                                               ` cond* João Távora
  2023-12-21 16:01                                                 ` [External] : cond* Drew Adams
@ 2023-12-24  3:57                                                 ` Richard Stallman
  1 sibling, 0 replies; 342+ messages in thread
From: Richard Stallman @ 2023-12-24  3:57 UTC (permalink / raw)
  To: João Távora; +Cc: emacs-devel

[[[ To any NSA and FBI agents reading my email: please consider    ]]]
[[[ whether defending the US Constitution against all enemies,     ]]]
[[[ foreign or domestic, requires you to follow Snowden's example. ]]]

  > > Are you talking about this?
  > >
  > >    (cond*
  > >        ((match* `(expt ,foo ,bar) x))
  > >        (t
  > >             (something-that-depends-on FOO BAR) ; is this how to use it?
  > >        )

  > Yes.  It is very simple.  In Elisp or any Lisp I know, forms that
  > introduce bindings are also the containers of any forms that use
  > such bindings, most notable case being (let VARLIST BODY...)

The that introduces these bindings is let, and it also contains them.
Likewise for cond*.

match* and bind* are not independent constructs -- they are defined as
part of cond*.  They are used within a cond* to specify the bindings
for it.  It is a little more complex than the way let* makes bindings
but not very different.

This is a generalization of a feature of pcase.  A pcase clause's
pattern may specify bindings that are not contained within that
pattern.  They are contained within the pcase form.

The same is true for cond*, but since it has different kinds of
clauses, match* and bind* identify clauses whose first element can
make bindings.  These bindings are specified by part of the cond* form
and contained within the cond* form.

(Formerly I proposed the keywords :match and :bind to
mark this, but it's equivalent except for syntax.)

-- 
Dr Richard Stallman (https://stallman.org)
Chief GNUisance of the GNU Project (https://gnu.org)
Founder, Free Software Foundation (https://fsf.org)
Internet Hall-of-Famer (https://internethalloffame.org)





^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: cond*
  2023-12-22  7:27                                                 ` cond* Philip Kaludercic
@ 2023-12-25  3:41                                                   ` Richard Stallman
  2023-12-25 12:32                                                     ` cond* Philip Kaludercic
  0 siblings, 1 reply; 342+ messages in thread
From: Richard Stallman @ 2023-12-25  3:41 UTC (permalink / raw)
  To: Philip Kaludercic; +Cc: emacs-devel

[[[ To any NSA and FBI agents reading my email: please consider    ]]]
[[[ whether defending the US Constitution against all enemies,     ]]]
[[[ foreign or domestic, requires you to follow Snowden's example. ]]]

I'm going to finish designing the specs of cond* before trying to
implement it.  To implement each of the different spec versions
would have been a lot more work than is really necessary.
-- 
Dr Richard Stallman (https://stallman.org)
Chief GNUisance of the GNU Project (https://gnu.org)
Founder, Free Software Foundation (https://fsf.org)
Internet Hall-of-Famer (https://internethalloffame.org)





^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: cond*
  2023-12-25  3:41                                                   ` cond* Richard Stallman
@ 2023-12-25 12:32                                                     ` Philip Kaludercic
  2023-12-27  4:54                                                       ` cond* Richard Stallman
  0 siblings, 1 reply; 342+ messages in thread
From: Philip Kaludercic @ 2023-12-25 12:32 UTC (permalink / raw)
  To: Richard Stallman; +Cc: emacs-devel

Richard Stallman <rms@gnu.org> writes:

> [[[ To any NSA and FBI agents reading my email: please consider    ]]]
> [[[ whether defending the US Constitution against all enemies,     ]]]
> [[[ foreign or domestic, requires you to follow Snowden's example. ]]]
>
> I'm going to finish designing the specs of cond* before trying to
> implement it.  To implement each of the different spec versions
> would have been a lot more work than is really necessary.

Having a rough prototype of an implementation would still be useful to
have, to get a better felling of what the macro should look and feel
like.  An advantage of `pcase' (as with Emacs) is that it is extensible
and can be adapted to new needs.  My fear is that if `cond*' is conjured
up in our minds, it is easy to misunderstand the needs in practice, or
if it really will be easier to use.  E.g. from reading your messages, I am
still not sure how `cond*' and `match' are supposed to interact with one
another.



^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: cond*
  2023-12-24  3:57                                                 ` cond* Richard Stallman
@ 2023-12-25 14:14                                                   ` Ihor Radchenko
  0 siblings, 0 replies; 342+ messages in thread
From: Ihor Radchenko @ 2023-12-25 14:14 UTC (permalink / raw)
  To: rms; +Cc: joaotavora, emacs-devel

Richard Stallman <rms@gnu.org> writes:

> Yesterday I rewrote the documentation of constrained variables and
> sent that to the list.  Does that version make this clear?

Having a documentation certainly helps :)
I still find the construct problematic though - will reply to the email
describing the PRED construct.

-- 
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] 342+ messages in thread

* Re: Instead of pcase
  2023-12-23  2:53                                               ` Richard Stallman
@ 2023-12-25 14:26                                                 ` Ihor Radchenko
  2023-12-27  4:54                                                   ` Richard Stallman
  0 siblings, 1 reply; 342+ messages in thread
From: Ihor Radchenko @ 2023-12-25 14:26 UTC (permalink / raw)
  To: rms; +Cc: Adam Porter, emacs-devel

Richard Stallman <rms@gnu.org> writes:

> Constrained variable: (PRED VARIABLE)  or, more generally,
>                       (PRED VARIABLE OTHER-ARGS...)
> ...
>      (symbolp sym)   ; Match any symbol, bind `sym' to it.

This one is clear, especially as ,(symbolp sym) - comma indicates that
the form is special.

>      (> num-foos min-foos)  ; Match any number greater than MIN-FOOS,
>                             ;  bind `num-foos' to it.

But this is confusing - which symbol to bind and which one to eval is
based purely on position in the ,(PRED ...) pattern. In such scenario,
it is very easy to confuse that num-foos will be let-bound. It does not
help that the whole thing looks like an ordinary function call.

I'd suggest to provide a more clear indication about which symbol will
be bound, so that it stands out compared to ordinary variables like
min-foos.

>   Constrained variable constructs can be nested
>
>   For example,
>
>     (< (integerp num-foos) 1)  ; Match any integer number > 1,
>                                ;  bind `num-foos' to it.

This is also confusing. Looking at the above expression, I expect that
we compare the return value of `integerp' with 1, but it is not the case
- integerp returns nil or t. Again, it looks deceivingly similar to
normal function call.

> General constrained variable: (constrain VAR EXPRESSION)
>
>   This general constrained variable pattern binds VAR to the
>   value being matched against, tentatively, then evaluates EXPRESSION.
>   If the result is true, the match succeeds and leaves VAR
>   bound to that value.
>
>   For instance,
>
>     (constrain x (and (> x 0) (< x 100)))
>
>   succeeds if the value being matched aainst is in the open interval (0, 100),
>   and in that case it binds x to that value.

This looks much better, as `constrain' is a special keyword that can be
easily recognized and not confused with a function call.

-- 
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] 342+ messages in thread

* Re: Instead of pcase
  2023-12-25 14:26                                                 ` Ihor Radchenko
@ 2023-12-27  4:54                                                   ` Richard Stallman
  2023-12-28 13:05                                                     ` Ihor Radchenko
  0 siblings, 1 reply; 342+ messages in thread
From: Richard Stallman @ 2023-12-27  4:54 UTC (permalink / raw)
  To: Ihor Radchenko; +Cc: emacs-devel

[[[ To any NSA and FBI agents reading my email: please consider    ]]]
[[[ whether defending the US Constitution against all enemies,     ]]]
[[[ foreign or domestic, requires you to follow Snowden's example. ]]]

  > >      (> num-foos min-foos)  ; Match any number greater than MIN-FOOS,
  > >                             ;  bind `num-foos' to it.

  > But this is confusing - which symbol to bind and which one to eval is
  > based purely on position in the ,(PRED ...) pattern.

As this states

    > Constrained variable: (PRED VARIABLE)  or, more generally,
    >                       (PRED VARIABLE OTHER-ARGS...)

the pattern variable to bind is always the second element of that list
-- what would be the first "argument" of PRED, if this ere a normal
function call.  Thus, in

      (> num-foos min-foos)

the variable to bind is `num-foos', and `min-foos' is simply an expression
to evaluate.

The comments after it restate that:

                             ; Match any number greater than MIN-FOOS,
                             ;  bind `num-foos' to it.

Is it clear now what that pattern means?

Can you suggest what aspects of that (or other) text to improve?



-- 
Dr Richard Stallman (https://stallman.org)
Chief GNUisance of the GNU Project (https://gnu.org)
Founder, Free Software Foundation (https://fsf.org)
Internet Hall-of-Famer (https://internethalloffame.org)





^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: cond*
  2023-12-25 12:32                                                     ` cond* Philip Kaludercic
@ 2023-12-27  4:54                                                       ` Richard Stallman
  2023-12-27 14:34                                                         ` cond* Philip Kaludercic
  0 siblings, 1 reply; 342+ messages in thread
From: Richard Stallman @ 2023-12-27  4:54 UTC (permalink / raw)
  To: Philip Kaludercic; +Cc: emacs-devel

[[[ To any NSA and FBI agents reading my email: please consider    ]]]
[[[ whether defending the US Constitution against all enemies,     ]]]
[[[ foreign or domestic, requires you to follow Snowden's example. ]]]

  > Having a rough prototype of an implementation would still be useful to
  > have, to get a better felling of what the macro should look and feel
  > like.

Yes, it might do that.  Would you like to help write it?
I think some parts of the pcase code could be adapted.

  > E.g. from reading your messages, I am
  > still not sure how `cond*' and `match' are supposed to interact with one
  > another.

`match*' is not an independent construct defined on its own.
It is meaningful only within a cond* construct.  In effect,
it marks a certain part of the cond*.

If someone can figure out a way that `match*' could be meaningful on
its own, whi;e also working together with `cond*' so that the two
function together as desired, that would be a neat hack.  But I'm not
aiming for that.


-- 
Dr Richard Stallman (https://stallman.org)
Chief GNUisance of the GNU Project (https://gnu.org)
Founder, Free Software Foundation (https://fsf.org)
Internet Hall-of-Famer (https://internethalloffame.org)





^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: cond*
  2023-12-27  4:54                                                       ` cond* Richard Stallman
@ 2023-12-27 14:34                                                         ` Philip Kaludercic
  2023-12-29  3:52                                                           ` cond* Richard Stallman
  0 siblings, 1 reply; 342+ messages in thread
From: Philip Kaludercic @ 2023-12-27 14:34 UTC (permalink / raw)
  To: Richard Stallman; +Cc: emacs-devel

Richard Stallman <rms@gnu.org> writes:

> [[[ To any NSA and FBI agents reading my email: please consider    ]]]
> [[[ whether defending the US Constitution against all enemies,     ]]]
> [[[ foreign or domestic, requires you to follow Snowden's example. ]]]
>
>   > Having a rough prototype of an implementation would still be useful to
>   > have, to get a better felling of what the macro should look and feel
>   > like.
>
> Yes, it might do that.  Would you like to help write it?
> I think some parts of the pcase code could be adapted.

I have some time and could try it out.  Can you link me to the most
current specification?

>   > E.g. from reading your messages, I am
>   > still not sure how `cond*' and `match' are supposed to interact with one
>   > another.
>
> `match*' is not an independent construct defined on its own.
> It is meaningful only within a cond* construct.  In effect,
> it marks a certain part of the cond*.
>
> If someone can figure out a way that `match*' could be meaningful on
> its own, whi;e also working together with `cond*' so that the two
> function together as desired, that would be a neat hack.  But I'm not
> aiming for that.

I agree, that would be interesting to have.



^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: Instead of pcase
  2023-12-27  4:54                                                   ` Richard Stallman
@ 2023-12-28 13:05                                                     ` Ihor Radchenko
  2023-12-30  3:20                                                       ` Richard Stallman
  0 siblings, 1 reply; 342+ messages in thread
From: Ihor Radchenko @ 2023-12-28 13:05 UTC (permalink / raw)
  To: rms; +Cc: emacs-devel

Richard Stallman <rms@gnu.org> writes:

>   > >      (> num-foos min-foos)  ; Match any number greater than MIN-FOOS,
>   > >                             ;  bind `num-foos' to it.
>
>   > But this is confusing - which symbol to bind and which one to eval is
>   > based purely on position in the ,(PRED ...) pattern.
>
> As this states
>
>     > Constrained variable: (PRED VARIABLE)  or, more generally,
>     >                       (PRED VARIABLE OTHER-ARGS...)
>
> the pattern variable to bind is always the second element of that list
> ...
> Is it clear now what that pattern means?
> Can you suggest what aspects of that (or other) text to improve?

I did not mean that I do not understand the description of PRED form.
I just find the syntax you proposed confusing - it is too similar to the
ordinary Elisp forms. Especially when we start nesting "constrained
variable" constructs.

For example, consider matching a list of two integers where the second
element is both larger than the first and also divisible by 5 when
subtracted variable DEC:

`(,(integerp smaller) ,(> (= (mod (- (integerp bigger) dec) 5) 0) smaller))

-- 
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] 342+ messages in thread

* Re: cond*
  2023-12-27 14:34                                                         ` cond* Philip Kaludercic
@ 2023-12-29  3:52                                                           ` Richard Stallman
  2024-01-01 14:49                                                             ` cond* Ihor Radchenko
  0 siblings, 1 reply; 342+ messages in thread
From: Richard Stallman @ 2023-12-29  3:52 UTC (permalink / raw)
  To: Philip Kaludercic; +Cc: emacs-devel

[[[ To any NSA and FBI agents reading my email: please consider    ]]]
[[[ whether defending the US Constitution against all enemies,     ]]]
[[[ foreign or domestic, requires you to follow Snowden's example. ]]]

I include below the latest version.

Compare the total complexity of specification of cond* with the total
complexity of specification of pcase.  Then likewise compare the
generality and flexibility of cond* with pcase.

Each clause in cond* that has just one element -- no "clause body" --
is a "non-exit" clause.  After that clause completes, control always
proceeds to the following clause.

All other clauses are like cond clauses, in that when the condition is
true, the executes its clause body and then exits the cond*.

  (cond* 
       ;; Same as a clause in `cond',
       (CONDITION
        DO-THIS-IF-TRUE-THEN-EXIT...)

       ;; Execute FORM and ignore its value.
       (FORM)

       ;; Variables to bind, as in let*, around the rest
       ;; of the cond*.
       ((bind* (x foobar) y z (foo 5) a))
       ;; Bindings continue in effect for the whole cond* construct.

       ;; Bind variables for the clause, as in let*.
       ((bind* (foo 5) (condition (hack-it foo)))
        ;; condition is that the last variable bound be non-nil.
        BODY...)
       ;; Bindings no longer in effect.

       ;; Extracts substructure and binds variables for the clause.
       ((match* `(expt ,foo ,bar) x)
        DO-THIS-IF-IT-MATCHED-THEN-EXIT...)
       ;; Bindings no longer in effect.

       ;; Extracts substructure and binds variables
       ;; for the rest of the cond*.
       ;; Like above but always falls thru to next clause.
       ;; All the variables mentioned in the pattern
       ;; are bound whether match succeeds or not.
       ;; If a value can be determined from an incomplete match,
       ;; the variable gets that value.
       ((match* `(expt ,foo ,bar) x))
       ;; Bindings continue in effect.

       ;; Another example of fall-through match* clause.
       ;; All the variables mentioned in the pattern
       ;; are bound in all cases.
       ((match* (or `() `(,macroexp-const-p const)) body)

;; The `match-set*' is a tentative proposal.  It may not be worth including.
       ;; Extracts substructure and sets variables if match succeeds
       ((match-set* `(expt ,foo ,bar) x)
        DO-THIS-IF-IT-MATCHED-THEN-EXIT...)

       ;; Extracts substructure and sets variables without binding them.
       ;; Always falls thru to next clause.
       ((match-set* `(expt ,foo ,bar) x))
       )

To execute several expressions and not exit, use this:

       ((progn DO-THIS-UNCONDITIONALLY-AND-DONT-STOP...)

To test CONDITION and return its value if non-nil, use this:

       (CONDITION CONDITION)

That is the best way when CONDITION is simple.  When it is complex,
this may be clearer and shorter than repeating CONDITION:

       ((bind* (value CONDITION))
        value)
\f
**Possible types of patterns for match*.

CONSTANT: nil, t, a keyword, a quoted constant other than a cons cell,
          fixed parts of a backquote.

  This matches any value equal to CONSTANT.

_

  _ means to match any value and not store it anywhere.

VARIABLE: a symbol

  A symbol means to match any value and set VARIABLE to it.

A backquoted cons cell

  The car and the cdr are subpattenrs.  The cons cell pattern
  matches any cons cell whose car and cdr match those two subpatterns.
  How nil as a cdr matches is controlled by the match-nil flag.

  When the nil-match-all flag is false, nil as a cdr matches
  only nil itself.

  When the nil-match-all flag is true, nil as a cdr matches
  any object and ignores that object.

  The nil-match-all flag is false by default.  The `cdr' pattern maks
  it false within its its subpattern, and the `cdr-safe' pattern makes
  it true forwithin its its subpattern.

(cdr-safe QUOTED-CONS-CELL)

  This pattern is equivalent to QUOTED-CONS-CELL by itself
  except that it makes the nil-match-all flag true within it.

     (cdr-safe `(a b))  matches (a b), (a b c), (a b . d), etc.

(cdr QUOTED-CONS-CELL)

  This pattern is equivalent to QUOTED-CONS-CELL by itself
  except that it makes the nil-match-all flag false within it.

     (cdr `(a b))  matches only (a b).

A backquoted vector

  Each element is a subpattern.  This
  matches a vector of data if each element of that vector is
  matched by the corresponding subpattern.

A backquoted structure constructor

  Each field is a subpattern.  This matches a structure as data if
  each field element of that structure is matched by the corresponding
  subpattern.

Constrained variable: (PRED VARIABLE)  or, more generally,
                      (PRED VARIABLE OTHER-ARGS...)

  This matches any value VALUE that satisfies the specified
  constraint.  PRED is a function to test the constraint.  It receives
  VALUE as its first argument.  If PRED returns true, that means VALUE
  satisfies the constraint, so this pattern binds (or sets) VARIABLE
  to that value.  For instance,

     (symbolp sym)   ; Match any symbol, bind `sym' to it.

xxxxxxxxxxxxxx not decided yet
    This would give some added power, but does that power really enable
    the user to do more with cond*?  I am not sure.

  PATTERN can also be a list, which is a pattern to destructure,
  For instance,

     (plistp `(,a ,b . ,rest))

  checks that VA<UE is a valid plist, then binds a and b to the first
  and second element and binds rest to its cddr.
xxxxxxxxxxxxxx not decided yet

  If you wish, you can specify additional arguments to pass to PRED.
  The OTHER-ARGS are not patterns to match, they are Lisp expressions
  whose values specify the additional arguments to pass to PRED,
  following the first argument which is VALUE.  In effect, the call
  to PRED looks like this:

      (apply PRED VALUE (mapcar 'eval OTHER-ARGS))

  Here are two examples of passing an additional argument.
 
     (> num-foos 1)  ; Match any number greater than 1, bind `num-foos' to it.
     (> num-foos min-foos)  ; Match any number greater than MIN-FOOS,
                            ;  bind `num-foos' to it.

  When matching to bind variables, the presence of a constrained
  variable pattern, as a subpattern of the overall pattern to be
  matched, unconditionally binds VARIABLE whether the subpattern
  matches or not.

  Errors in constrained variable constructs:

  If an error occurs in testing the constraint, or calculating 
  the other arguments to pass to the predicate, that pattern fails
  to match but does not terminate the cond* form.

  Constrained variable constructs can be nested:

  For example,


    (integerp (> num-foos 1))  ; Match any integer > 1,
                               ;  bind `num-foos' to it.

  nests the constrained pattern (integerp num-foos) inside the
  constrained pattern (< ... 1).  This nested constrained pattern
  first tests that the value is greater than 1, then tests it is an
  integer.  If both of those constraints are true, it setse `num-foos'.

    (> (integerp num-foos) 1)  ; Match any integer > 1,
                               ;  bind `num-foos' to it.

  does the two tests in the opposite order; it is equivalent, because
  an error in the call to `>' only makes this pattern fail to match.

  Advanced hack for experts: the OTHER-ARGS can refer to variables
  bound earlier in this pattern-matching operation.  For example,

  `(,(integerp smaller) ,(> (integerp bigger) smaller))
     ; Matches a list of two integers in which the second integer
     ; is larger than the first.

  (or `(,(integerp smaller) ,(> (integerp bigger) smaller))
      `(,(integerp bigger) ,(< (integerp smaller) bigger)))
     ; matches a ist of two integers and binds `bigger' to the bigger one
     ; and `smaller' to the smaller one.

  However, it might be cleaner to match the two integers regardless of
  their numberical ordering, then in Lisp code see which one is larger.

General constrained variable: (constrain VAR EXPRESSION)

  This general constrained variable pattern binds VAR to the
  value being matched against, tentatively, then evaluates EXPRESSION.
  If the result is true, the match succeeds and leaves VAR
  bound to that value.

  For instance,

    (constrain x (and (> x 0) (< x 100)))

  succeeds if the value being matched aainst is in the open interval (0, 100),
  and in that case it binds x to that value.

Alternatives: (or SUBPATTERNS...)

  This tries to match each of the SUBPATTERNS in order until one matches.
  If the pattern is being used to bind variables, it binds all the variables
  specified in any of SUBPATTERNS
\f
These three ways of using `cond*' are worth noting.

(cond* ((match*  PATTERN VALUE) TEST))

       PATTERN is a pattern as described above.  For instance
       (match `(+ (expt ,_ ,_)) (get-complex-list))
       would decompose the result of (get-complex-list) and check
       for `+' and `expt' in it.

       PATTERN will not be evaluated, just used as guidance when the
       `match' form is macroexpanded.

       If PATTERN includes substitutions, it will virtually perform
       those substitutions and compare parts of VALUE against them.
       (match `(foo ,foo) x) compares (car x) with `foo'.

       TEST is a Lisp expression to be evaluated if VALUE seems
       to fit PATTERN.  If TEST evaluates non-nil, the match succeeds.

       `match' returns t if it succeeds in matching, otherwise nil.

       `match' can also handle vectors and maybe some other kinds of
       structures.


(cond* ((match-set*  PATTERN VALUE)))

       PATTERN is a pattern as described above.  For instance
       (match-set `(+ ,y ,z) (get-complex-list))
       would decompose the result of (get-complex-list), verify the car,
       and set y and z.  It is equivalent to this:

       (if (eq (car value) '+)
           (progn
             (setq y (car (cadr value)) z (cadr (cadr value)))
             TEST))

       PATTERN will not be evaluated, just used as guidance when the
       `match-set' form is macroexpanded, producing code like this:

       TEST is a Lisp expression to be evaluated if VALUE seems
       to fit PATTERN.  If TEST evaluates non-nil, the match succeeds.

       `match-set' returns t if it succeeds in matching, otherwise nil.
       
       `match-set' can also handle vectors and maybe some other kinds of
       structures.


(cond* ((match*  PATTERN VALUE) BODY...))

       Like the previous, except that instead of setting the
       variables found in PATTERN, it let-binds them and runs BODY
       with those bindings.

-- 
Dr Richard Stallman (https://stallman.org)
Chief GNUisance of the GNU Project (https://gnu.org)
Founder, Free Software Foundation (https://fsf.org)
Internet Hall-of-Famer (https://internethalloffame.org)





^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: Instead of pcase
  2023-12-28 13:05                                                     ` Ihor Radchenko
@ 2023-12-30  3:20                                                       ` Richard Stallman
  2024-01-01 14:33                                                         ` Ihor Radchenko
  0 siblings, 1 reply; 342+ messages in thread
From: Richard Stallman @ 2023-12-30  3:20 UTC (permalink / raw)
  To: Ihor Radchenko; +Cc: emacs-devel

[[[ To any NSA and FBI agents reading my email: please consider    ]]]
[[[ whether defending the US Constitution against all enemies,     ]]]
[[[ foreign or domestic, requires you to follow Snowden's example. ]]]

  > `(,(integerp smaller) ,(> (= (mod (- (integerp bigger) dec) 5) 0) smaller))

That is not a valid constrained variable pattern, because
    (mod (- (integerp bigger) dec) 5)
is nt a valid constrained variable pattern.

In a constrained variable pattern, the cadr has to be a _variable pattern_.
It can be a plain symbol, or it can be another constrained variable pattern.

For tests which don't fit that form, you can use `constrain'.
Here's a valid example:

`(,(integerp smaller)
  ,(constrain bigger (> (= (mod (- (integerp bigger) dec) 5) 0) smaller)))

Does the text I sent fail to make this clear?  Would you please take
a look, and if it is not clear, tell me why?

-- 
Dr Richard Stallman (https://stallman.org)
Chief GNUisance of the GNU Project (https://gnu.org)
Founder, Free Software Foundation (https://fsf.org)
Internet Hall-of-Famer (https://internethalloffame.org)





^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: Instead of pcase
  2023-12-30  3:20                                                       ` Richard Stallman
@ 2024-01-01 14:33                                                         ` Ihor Radchenko
  2024-01-03  4:13                                                           ` Richard Stallman
  2024-01-03  4:13                                                           ` Richard Stallman
  0 siblings, 2 replies; 342+ messages in thread
From: Ihor Radchenko @ 2024-01-01 14:33 UTC (permalink / raw)
  To: rms; +Cc: emacs-devel

Richard Stallman <rms@gnu.org> writes:

> For tests which don't fit that form, you can use `constrain'.
> Here's a valid example:
>
> `(,(integerp smaller)
>   ,(constrain bigger (> (= (mod (- (integerp bigger) dec) 5) 0) smaller)))
>
> Does the text I sent fail to make this clear?  Would you please take
> a look, and if it is not clear, tell me why?

Your description is clear. However, it is somewhat similar to the
existing `pcase' description in a way that it is also clear, but goes in
odds with the usual Elisp structures - I see nested "constrained
variable" construct yet as another DSL. I see myself coming to back the
documentation of `cond*' again and again, just as I do with `pcase' now.

Let me try to illustrate the problem with another example:

    ;; ALIST-VAL = '((:key1 . 1) (:key4 . 2))
    ;; Match alist key where the key is one of a know set of keys.
    (match* (memq (alist-get key alist-val) '(:key1 :key2 :key3)) :key1)

From the description of "constrained variable" construct, the above will
(1) test if ALIST-VAL contains a record with KEY=:key1 key; (2) test if
KEY=:key1 is one of :key1 :key2 :key3.

However, the above is also deceivingly similar to Elisp expression that
tests the return value of `alist-get': (memq 1 '(:key1 :key2 :key3))

-- 
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] 342+ messages in thread

* Re: cond*
  2023-12-29  3:52                                                           ` cond* Richard Stallman
@ 2024-01-01 14:49                                                             ` Ihor Radchenko
  2024-01-03  4:13                                                               ` cond* Richard Stallman
                                                                                 ` (2 more replies)
  0 siblings, 3 replies; 342+ messages in thread
From: Ihor Radchenko @ 2024-01-01 14:49 UTC (permalink / raw)
  To: rms; +Cc: Philip Kaludercic, emacs-devel

Richard Stallman <rms@gnu.org> writes:

> Each clause in cond* that has just one element -- no "clause body" --
> is a "non-exit" clause.  After that clause completes, control always
> proceeds to the following clause.
> ...
> To test CONDITION and return its value if non-nil, use this:
>
>        (CONDITION CONDITION)

Note that it is different from `cond', which is somewhat confusing -
(CONDITION) in `cond' exits, returning CONDITION value.

> A backquoted cons cell
>
> ...
> (cdr-safe QUOTED-CONS-CELL)
>
>   This pattern is equivalent to QUOTED-CONS-CELL by itself
>   except that it makes the nil-match-all flag true within it.
>
>      (cdr-safe `(a b))  matches (a b), (a b c), (a b . d), etc.
>
> (cdr QUOTED-CONS-CELL)
>
>   This pattern is equivalent to QUOTED-CONS-CELL by itself
>   except that it makes the nil-match-all flag false within it.
>
>      (cdr `(a b))  matches only (a b).

This is more confusing than `pcase'. In `pcase', what you call
"cdr-safe" is realized simply by `(a b . _) and what you cal ""cdr" is
`(a b). I find `pcase' version both more intuitive and more compact.

> Constrained variable: (PRED VARIABLE)  or, more generally,
>                       (PRED VARIABLE OTHER-ARGS...)
>
>   This matches any value VALUE that satisfies the specified
>   constraint.  PRED is a function to test the constraint.  It receives
>   VALUE as its first argument.  If PRED returns true, that means VALUE
>   satisfies the constraint, so this pattern binds (or sets) VARIABLE
>   to that value.  For instance,
>
>      (symbolp sym)   ; Match any symbol, bind `sym' to it.

This is an equivalent of pcase's pred pattern, except that pcase also
allow VARIABLE to be non-first argument of PRED.
What about allowing a construct like ,((plist-get plist) property) that
will test for PROPERTY being in PLIST?

Or, better, allow VARIABLE to be in an arbitrary argument of PRED:

,(PRED ARG1 ARG2 !VARIABLE ARG3 ...)
Example: ,(plist-get plist !variable #'equal)

> xxxxxxxxxxxxxx not decided yet
>     This would give some added power, but does that power really enable
>     the user to do more with cond*?  I am not sure.
>
>   PATTERN can also be a list, which is a pattern to destructure,
>   For instance,
>
>      (plistp `(,a ,b . ,rest))
>
>   checks that VA<UE is a valid plist, then binds a and b to the first
>   and second element and binds rest to its cddr.
> xxxxxxxxxxxxxx not decided yet

I feel that layering conditions will lead to unnecessary complexity.
What about allowing (and ...) pattern, similar to (or ...):

(match* (and (plistp _) `(,a ,b . ,rest)) plist)

P.S. What is missing in the above compared to pcase is matching regular
expressions:

‘(rx RX-EXPR...)’
     Matches strings against the regexp RX-EXPR..., using the ‘rx’
     regexp notation (*note Rx Notation::), as if by ‘string-match’.

     In addition to the usual ‘rx’ syntax, RX-EXPR... can contain the
     following constructs:

     ‘(let REF RX-EXPR...)’
          Bind the symbol REF to a submatch that matches RX-EXPR....
          REF is bound in BODY-FORMS to the string of the submatch or
          ‘nil’, but can also be used in ‘backref’.

     ‘(backref REF)’
          Like the standard ‘backref’ construct, but REF can here also
          be a name introduced by a previous ‘(let REF ...)’ construct.

-- 
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] 342+ messages in thread

* Re: Instead of pcase
  2024-01-01 14:33                                                         ` Ihor Radchenko
@ 2024-01-03  4:13                                                           ` Richard Stallman
  2024-01-03  4:13                                                           ` Richard Stallman
  1 sibling, 0 replies; 342+ messages in thread
From: Richard Stallman @ 2024-01-03  4:13 UTC (permalink / raw)
  To: Ihor Radchenko; +Cc: emacs-devel

[[[ To any NSA and FBI agents reading my email: please consider    ]]]
[[[ whether defending the US Constitution against all enemies,     ]]]
[[[ foreign or domestic, requires you to follow Snowden's example. ]]]

  > existing `pcase' description in a way that it is also clear, but goes in
  > odds with the usual Elisp structures - I see nested "constrained
  > variable" construct yet as another DSL.

It took me a while to figure oiut what "DSL" stood for.

In another message I saw "E2E" and had to look it up.
It refers to a concept I am familiar with, but I never
saw that acronym before.

People, so that I can understand you, I ask you plesae to spell out
such expressions in full rather than using acronyms, unless we use
those acronyms here every day.  Each time you use an acronym that
maybe not all of us know, that may exclude someone from understanding.

Thank you.

-- 
Dr Richard Stallman (https://stallman.org)
Chief GNUisance of the GNU Project (https://gnu.org)
Founder, Free Software Foundation (https://fsf.org)
Internet Hall-of-Famer (https://internethalloffame.org)





^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: Instead of pcase
  2024-01-01 14:33                                                         ` Ihor Radchenko
  2024-01-03  4:13                                                           ` Richard Stallman
@ 2024-01-03  4:13                                                           ` Richard Stallman
  2024-01-03 16:08                                                             ` Ihor Radchenko
  1 sibling, 1 reply; 342+ messages in thread
From: Richard Stallman @ 2024-01-03  4:13 UTC (permalink / raw)
  To: Ihor Radchenko; +Cc: emacs-devel

[[[ To any NSA and FBI agents reading my email: please consider    ]]]
[[[ whether defending the US Constitution against all enemies,     ]]]
[[[ foreign or domestic, requires you to follow Snowden's example. ]]]

  > Let me try to illustrate the problem with another example:

  >     ;; ALIST-VAL = '((:key1 . 1) (:key4 . 2))
  >     ;; Match alist key where the key is one of a know set of keys.
  >     (match* (memq (alist-get key alist-val) '(:key1 :key2 :key3)) :key1)

  > >From the description of "constrained variable" construct, the above will
  > (1) test if ALIST-VAL contains a record with KEY=:key1 key; (2) test if
  > KEY=:key1 is one of :key1 :key2 :key3.

What a strange example.  This is connterintuitive and I could not see
at first what it would mean.  But I worked it out by following the
rules.

(match* PATTERN :key1) matches PATTERN against the data object :key1.

(memq (alist-get key alist-val) '(:key1 :key2 :key3))
as a pattern means to match (alist-get key alist-val) aainst it,
and if that matches, then call memq to determine whether this matches,

It would be matched against :key1.

Matching (alist-get key alist-val) against :key1 would succeed,
so `key' would be bound to `key1'.

So the memq call would return t.  And the pattern would match,
binding `key' to :key1.

It isn't "wrong", but I can't see the point using that strange 
pattern.  What purpose did you have in mind in writing it?
Is there a simpler way to do that?


-- 
Dr Richard Stallman (https://stallman.org)
Chief GNUisance of the GNU Project (https://gnu.org)
Founder, Free Software Foundation (https://fsf.org)
Internet Hall-of-Famer (https://internethalloffame.org)





^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: cond*
  2024-01-01 14:49                                                             ` cond* Ihor Radchenko
@ 2024-01-03  4:13                                                               ` Richard Stallman
  2024-01-03 15:57                                                                 ` cond* Ihor Radchenko
  2024-01-03  4:13                                                               ` cond* Richard Stallman
  2024-01-03  4:13                                                               ` cond* Richard Stallman
  2 siblings, 1 reply; 342+ messages in thread
From: Richard Stallman @ 2024-01-03  4:13 UTC (permalink / raw)
  To: Ihor Radchenko; +Cc: emacs-devel

[[[ To any NSA and FBI agents reading my email: please consider    ]]]
[[[ whether defending the US Constitution against all enemies,     ]]]
[[[ foreign or domestic, requires you to follow Snowden's example. ]]]

  > What about allowing a construct like ,((plist-get plist) property) that
  > will test for PROPERTY being in PLIST?

I do not understand what you mean by  ,((plist-get plist) property).
I am simply lost here.  I don't know which parts of that are supposed
to be fixed structure and which parts refer to things in the cond* call.

  > Or, better, allow VARIABLE to be in an arbitrary argument of PRED:

I understand that in the abstract.  I just don't see any syntax that
makes sense to use for it.

  > ,(PRED ARG1 ARG2 !VARIABLE ARG3 ...)

I don't understand this syntax.  `!' as no special meaning.
It cam't magically have a special meaning in a cpnd* pattern.
It would be part of the variable name.

This feature makes sense, and I've defined a syntax for it already:

   (constrain VARIABLE (PRED ARG1 ARG2 VARIABLE ARG3...))


-- 
Dr Richard Stallman (https://stallman.org)
Chief GNUisance of the GNU Project (https://gnu.org)
Founder, Free Software Foundation (https://fsf.org)
Internet Hall-of-Famer (https://internethalloffame.org)





^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: cond*
  2024-01-01 14:49                                                             ` cond* Ihor Radchenko
  2024-01-03  4:13                                                               ` cond* Richard Stallman
@ 2024-01-03  4:13                                                               ` Richard Stallman
  2024-01-03 15:48                                                                 ` cond* Ihor Radchenko
  2024-01-03  4:13                                                               ` cond* Richard Stallman
  2 siblings, 1 reply; 342+ messages in thread
From: Richard Stallman @ 2024-01-03  4:13 UTC (permalink / raw)
  To: Ihor Radchenko; +Cc: emacs-devel

[[[ To any NSA and FBI agents reading my email: please consider    ]]]
[[[ whether defending the US Constitution against all enemies,     ]]]
[[[ foreign or domestic, requires you to follow Snowden's example. ]]]

  > ‘(rx RX-EXPR...)’
  >      Matches strings against the regexp RX-EXPR..., using the ‘rx’
  >      regexp notation (*note Rx Notation::), as if by ‘string-match’.

That seems natural enough, though I don't recall the details of `rx'.
(I have never used it myself.)  But I need to underdstand this too:

       > In addition to the usual ‘rx’ syntax, RX-EXPR... can contain the
       > following constructs:

       > ‘(let REF RX-EXPR...)’
            > Bind the symbol REF to a submatch that matches RX-EXPR....
            > REF is bound in BODY-FORMS to the string of the submatch or
            > ‘nil’, but can also be used in ‘backref’.

I don't understand that description.  I don't see what this construct
would look like inside of an (rx ...) pattern, let alone what it would
mean.

Can you show me a complete pattern example using (rx...) and this, and
explain it?

-- 
Dr Richard Stallman (https://stallman.org)
Chief GNUisance of the GNU Project (https://gnu.org)
Founder, Free Software Foundation (https://fsf.org)
Internet Hall-of-Famer (https://internethalloffame.org)





^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: cond*
  2024-01-01 14:49                                                             ` cond* Ihor Radchenko
  2024-01-03  4:13                                                               ` cond* Richard Stallman
  2024-01-03  4:13                                                               ` cond* Richard Stallman
@ 2024-01-03  4:13                                                               ` Richard Stallman
  2024-01-03 15:50                                                                 ` cond* Ihor Radchenko
  2 siblings, 1 reply; 342+ messages in thread
From: Richard Stallman @ 2024-01-03  4:13 UTC (permalink / raw)
  To: Ihor Radchenko; +Cc: emacs-devel

[[[ To any NSA and FBI agents reading my email: please consider    ]]]
[[[ whether defending the US Constitution against all enemies,     ]]]
[[[ foreign or domestic, requires you to follow Snowden's example. ]]]

What should a string used as a pattern mean in cond*?
(What does it mean in pcase?)

Should it mean a usual Emacs regular expression to match against a string?

-- 
Dr Richard Stallman (https://stallman.org)
Chief GNUisance of the GNU Project (https://gnu.org)
Founder, Free Software Foundation (https://fsf.org)
Internet Hall-of-Famer (https://internethalloffame.org)





^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: cond*
  2024-01-03  4:13                                                               ` cond* Richard Stallman
@ 2024-01-03 15:48                                                                 ` Ihor Radchenko
  2024-01-06  4:31                                                                   ` cond* Richard Stallman
  0 siblings, 1 reply; 342+ messages in thread
From: Ihor Radchenko @ 2024-01-03 15:48 UTC (permalink / raw)
  To: rms; +Cc: emacs-devel

Richard Stallman <rms@gnu.org> writes:

>        > In addition to the usual ‘rx’ syntax, RX-EXPR... can contain the
>        > following constructs:
>
>        > ‘(let REF RX-EXPR...)’
>             > Bind the symbol REF to a submatch that matches RX-EXPR....
>             > REF is bound in BODY-FORMS to the string of the submatch or
>             > ‘nil’, but can also be used in ‘backref’.
>
> I don't understand that description.  I don't see what this construct
> would look like inside of an (rx ...) pattern, let alone what it would
> mean.
>
> Can you show me a complete pattern example using (rx...) and this, and
> explain it?

Sure.

Consider the following `rx' form that matches lines like "#+begin:
something":

(rx
    line-start (0+ (any " \t")) "#+BEGIN:" (0+ (any " \t"))
    ;; matches "something"
    (1+ word))

This is equivalent to

"^[	 ]*#\\+BEGIN:[	 ]*[[:word:]]+"

Now, consider that we need to extract "something" from the match if the
match succeeds:

(pcase "  #+begin: something"
  ((rx
    line-start (0+ (any " \t")) "#+BEGIN:" (0+ (any " \t"))
    ;; matches "something"
    ;; (let VAR <sub-expression>) binds VAR to sub-expression match.
    (let matched-value (1+ word)))
   (format "We just matched \"%s\"" matched-value))) ; => "We just matched \"something\""

-- 
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] 342+ messages in thread

* Re: cond*
  2024-01-03  4:13                                                               ` cond* Richard Stallman
@ 2024-01-03 15:50                                                                 ` Ihor Radchenko
  2024-01-06  4:31                                                                   ` cond* Richard Stallman
  0 siblings, 1 reply; 342+ messages in thread
From: Ihor Radchenko @ 2024-01-03 15:50 UTC (permalink / raw)
  To: rms; +Cc: emacs-devel

Richard Stallman <rms@gnu.org> writes:

> What should a string used as a pattern mean in cond*?
> (What does it mean in pcase?)
>
> Should it mean a usual Emacs regular expression to match against a string?

In `pcase', string pattern matches against a string:

(pcase "string"
  ("string" 'matched-string-by-equality)
  (_ 'not-matched)) ; => 'matched-string-by-equality

-- 
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] 342+ messages in thread

* Re: cond*
  2024-01-03  4:13                                                               ` cond* Richard Stallman
@ 2024-01-03 15:57                                                                 ` Ihor Radchenko
  2024-01-05  4:23                                                                   ` cond* Richard Stallman
  0 siblings, 1 reply; 342+ messages in thread
From: Ihor Radchenko @ 2024-01-03 15:57 UTC (permalink / raw)
  To: rms; +Cc: emacs-devel

Richard Stallman <rms@gnu.org> writes:

>   > Or, better, allow VARIABLE to be in an arbitrary argument of PRED:
>
> I understand that in the abstract.  I just don't see any syntax that
> makes sense to use for it.
>
>   > ,(PRED ARG1 ARG2 !VARIABLE ARG3 ...)
>
> I don't understand this syntax.  `!' as no special meaning.
> It cam't magically have a special meaning in a cpnd* pattern.
> It would be part of the variable name.

> This feature makes sense, and I've defined a syntax for it already:
>
>    (constrain VARIABLE (PRED ARG1 ARG2 VARIABLE ARG3...))

It is technically possible to assign special meaning to !name in macros.
However, I do agree that "constrain" should be good enough to the use
case that I proposed.


>   > What about allowing a construct like ,((plist-get plist) property) that
>   > will test for PROPERTY being in PLIST?
>
> I do not understand what you mean by  ,((plist-get plist) property).
> I am simply lost here.  I don't know which parts of that are supposed
> to be fixed structure and which parts refer to things in the cond* call.

[ I withdraw this proposal as "constrain" is good enough, but still
  replying to provide context for my previous idea ]

I was referring to what "pred" in `pcase' does:

‘(pred FUNCTION)’
     Matches if the predicate FUNCTION returns non-‘nil’ when called on
     EXPVAL.  The test can be negated with the syntax ‘(pred (not
     FUNCTION))’.  The predicate FUNCTION can have one of the following
     forms:

     function name (a symbol)
          Call the named function with one argument, EXPVAL.

          Example: ‘integerp’

     <...>

          function call with N args
          Call the function (the first element of the function call)
          with N arguments (the other elements) and an additional N+1-th
          argument that is EXPVAL.

          Example: ‘(= 42)’
          ^^^^^^^^^^^^^^^^^ <- this
          In this example, the function is ‘=’, N is one, and the actual
          function call becomes: ‘(= 42 EXPVAL)’.


-- 
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] 342+ messages in thread

* Re: Instead of pcase
  2024-01-03  4:13                                                           ` Richard Stallman
@ 2024-01-03 16:08                                                             ` Ihor Radchenko
  2024-01-05  4:23                                                               ` Richard Stallman
  0 siblings, 1 reply; 342+ messages in thread
From: Ihor Radchenko @ 2024-01-03 16:08 UTC (permalink / raw)
  To: rms; +Cc: emacs-devel

Richard Stallman <rms@gnu.org> writes:

>   >     ;; ALIST-VAL = '((:key1 . 1) (:key4 . 2))
>   >     ;; Match alist key where the key is one of a know set of keys.
>   >     (match* (memq (alist-get key alist-val) '(:key1 :key2 :key3)) :key1)
>
>   > >From the description of "constrained variable" construct, the above will
>   > (1) test if ALIST-VAL contains a record with KEY=:key1 key; (2) test if
>   > KEY=:key1 is one of :key1 :key2 :key3.
>
> What a strange example.  This is connterintuitive and I could not see
> at first what it would mean.  But I worked it out by following the
> rules.
> ...
> So the memq call would return t.  And the pattern would match,
> binding `key' to :key1.

> It isn't "wrong", but I can't see the point using that strange 
> pattern.  What purpose did you have in mind in writing it?
> Is there a simpler way to do that?

Let me try again to illustrate the point I wanted to make - the
(match* (PRED VAL ...)) construct can look too similar to ordinary Elisp
yet yielding different results that one would have to work out
consciously. This similarity may lead to confusion.

Consider another example:

(match* (xor (not var) t) t)

Unlike (match* (> (integerp bigger) 5) 10), where it is clear that
#'> cannot apply to the return value of #'integerp, my example with
#'xor may be tricky - one may confuse that #'xor is applied to the
return value of (not var) rather than to var itself.

More generally, my concern is that
(match* (PRED1 (PRED2 var) ARGS) val)
may be confusing for people reading the code because
(PRED1 (PRED2 var) ARGS) outside match* is also a valid Elisp code,
which returns a _different value_ compared to what happens inside
match*.

-- 
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] 342+ messages in thread

* Re: Instead of pcase
  2024-01-03 16:08                                                             ` Ihor Radchenko
@ 2024-01-05  4:23                                                               ` Richard Stallman
  2024-01-06 13:04                                                                 ` Ihor Radchenko
  0 siblings, 1 reply; 342+ messages in thread
From: Richard Stallman @ 2024-01-05  4:23 UTC (permalink / raw)
  To: Ihor Radchenko; +Cc: emacs-devel

[[[ To any NSA and FBI agents reading my email: please consider    ]]]
[[[ whether defending the US Constitution against all enemies,     ]]]
[[[ foreign or domestic, requires you to follow Snowden's example. ]]]

  > Consider another example:

  > (match* (xor (not var) t) t)

My first repsonse was to say that xor is not valid
in cond* patterns.  Indeed, I did not know that this
function `xor' existed.

But now I see that your example does fit the definition of
cond* patters, and its meaning is quite unintuitive.

I wonder why people defined `xor'.  It can't be used
as a conditional, like `and' and `or', so what is the point of it?

Anyway, I suppose the best response is to say that such counterintuitive
constrained variables are best avoided.  Or else specifically disallow
`xor' as PRED in a constrained variable.


-- 
Dr Richard Stallman (https://stallman.org)
Chief GNUisance of the GNU Project (https://gnu.org)
Founder, Free Software Foundation (https://fsf.org)
Internet Hall-of-Famer (https://internethalloffame.org)





^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: cond*
  2024-01-03 15:57                                                                 ` cond* Ihor Radchenko
@ 2024-01-05  4:23                                                                   ` Richard Stallman
  2024-01-06 14:33                                                                     ` cond* Ihor Radchenko
  0 siblings, 1 reply; 342+ messages in thread
From: Richard Stallman @ 2024-01-05  4:23 UTC (permalink / raw)
  To: Ihor Radchenko; +Cc: emacs-devel

[[[ To any NSA and FBI agents reading my email: please consider    ]]]
[[[ whether defending the US Constitution against all enemies,     ]]]
[[[ foreign or domestic, requires you to follow Snowden's example. ]]]

  > I was referring to what "pred" in `pcase' does:

  > ‘(pred FUNCTION)’
  >      Matches if the predicate FUNCTION returns non-‘nil’ when called on
  >      EXPVAL.  The test can be negated with the syntax ‘(pred (not
  >      FUNCTION))’.  The predicate FUNCTION can have one of the following
  >      forms:

Ok.  Given that for comparison, what conclusion or suggestion to you
offer about cond*?

-- 
Dr Richard Stallman (https://stallman.org)
Chief GNUisance of the GNU Project (https://gnu.org)
Founder, Free Software Foundation (https://fsf.org)
Internet Hall-of-Famer (https://internethalloffame.org)





^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: cond*
  2024-01-03 15:48                                                                 ` cond* Ihor Radchenko
@ 2024-01-06  4:31                                                                   ` Richard Stallman
  2024-01-06 13:09                                                                     ` cond* Ihor Radchenko
  0 siblings, 1 reply; 342+ messages in thread
From: Richard Stallman @ 2024-01-06  4:31 UTC (permalink / raw)
  To: Ihor Radchenko; +Cc: emacs-devel

[[[ To any NSA and FBI agents reading my email: please consider    ]]]
[[[ whether defending the US Constitution against all enemies,     ]]]
[[[ foreign or domestic, requires you to follow Snowden's example. ]]]

Now I understand what (let REF RX-EXPR...) does,  Thanks.

It seems like a gratuitous complexity for this aspect of `rx' to be
different between use in pcase and use as a Lisp function.

What Emacs really implements in search is numbered groups.
So that was the easiest thing to implement in `rx'.

But if it is possible to implement the named variables for thisin
pcase, surely they can be implemented in `rx' too.

How about if we add them to `rx'?  WDYT?

-- 
Dr Richard Stallman (https://stallman.org)
Chief GNUisance of the GNU Project (https://gnu.org)
Founder, Free Software Foundation (https://fsf.org)
Internet Hall-of-Famer (https://internethalloffame.org)





^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: cond*
  2024-01-03 15:50                                                                 ` cond* Ihor Radchenko
@ 2024-01-06  4:31                                                                   ` Richard Stallman
  2024-01-06 13:13                                                                     ` cond* Ihor Radchenko
  0 siblings, 1 reply; 342+ messages in thread
From: Richard Stallman @ 2024-01-06  4:31 UTC (permalink / raw)
  To: Ihor Radchenko; +Cc: emacs-devel

[[[ To any NSA and FBI agents reading my email: please consider    ]]]
[[[ whether defending the US Constitution against all enemies,     ]]]
[[[ foreign or domestic, requires you to follow Snowden's example. ]]]

  > > Should it mean a usual Emacs regular expression to match against a string?

  > In `pcase', string pattern matches against a string:

Since the idea is pattern-matching, I think that a regexp is natural
as well as more general.  Why not do this?

-- 
Dr Richard Stallman (https://stallman.org)
Chief GNUisance of the GNU Project (https://gnu.org)
Founder, Free Software Foundation (https://fsf.org)
Internet Hall-of-Famer (https://internethalloffame.org)





^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: Instead of pcase
  2024-01-05  4:23                                                               ` Richard Stallman
@ 2024-01-06 13:04                                                                 ` Ihor Radchenko
  2024-01-08  3:47                                                                   ` Richard Stallman
  0 siblings, 1 reply; 342+ messages in thread
From: Ihor Radchenko @ 2024-01-06 13:04 UTC (permalink / raw)
  To: rms; +Cc: emacs-devel

Richard Stallman <rms@gnu.org> writes:

>   > Consider another example:
>
>   > (match* (xor (not var) t) t)
>
> Anyway, I suppose the best response is to say that such counterintuitive
> constrained variables are best avoided.  Or else specifically disallow
> `xor' as PRED in a constrained variable.

My point is not about `xor' in particular.
What I am trying to demonstrate is that

(foo (bar var) arg) looks like a normal Elisp call - `foo' called with
two arguments: (bar var) and arg.

Yet, it has completely different meaning inside match*.

So, it is very easy to confuse match* clause result with return value of
the equivalent normal Elisp expression.

In contrast, a more explicit

(match* (constrain var (and (bar var) (foo var arg))) ...) 
(match* (constrain var (and (not var) (xor var t)) t) ...)

is much more natural and avoids confusion.

> ...
> I wonder why people defined `xor'.  It can't be used
> as a conditional, like `and' and `or', so what is the point of it?

`xor' can be used as conditional, and it also comes handy at time (we
have 7 functions using `xor' in Org mode, for example).
But that's off-topic to `pcase' discussion.

-- 
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] 342+ messages in thread

* Re: cond*
  2024-01-06  4:31                                                                   ` cond* Richard Stallman
@ 2024-01-06 13:09                                                                     ` Ihor Radchenko
  2024-01-08  3:47                                                                       ` cond* Richard Stallman
  0 siblings, 1 reply; 342+ messages in thread
From: Ihor Radchenko @ 2024-01-06 13:09 UTC (permalink / raw)
  To: rms; +Cc: emacs-devel

Richard Stallman <rms@gnu.org> writes:

> ...
> What Emacs really implements in search is numbered groups.
> So that was the easiest thing to implement in `rx'.
>
> But if it is possible to implement the named variables for thisin
> pcase, surely they can be implemented in `rx' too.
>
> How about if we add them to `rx'?  WDYT?

May you please elaborate how you see named variables in `rx'?

`rx' is a macro that transforms a sexp into string regexp. It does not
introduce let-bindings. So, I do not see any context to put named
variables within `rx' itself.

-- 
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] 342+ messages in thread

* Re: cond*
  2024-01-06  4:31                                                                   ` cond* Richard Stallman
@ 2024-01-06 13:13                                                                     ` Ihor Radchenko
  2024-01-08  3:47                                                                       ` cond* Richard Stallman
  0 siblings, 1 reply; 342+ messages in thread
From: Ihor Radchenko @ 2024-01-06 13:13 UTC (permalink / raw)
  To: rms; +Cc: emacs-devel

Richard Stallman <rms@gnu.org> writes:

>   > > Should it mean a usual Emacs regular expression to match against a string?
>
>   > In `pcase', string pattern matches against a string:
>
> Since the idea is pattern-matching, I think that a regexp is natural
> as well as more general.  Why not do this?

It is not very clear then how to match plain strings for equality.

-- 
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] 342+ messages in thread

* Re: cond*
  2024-01-05  4:23                                                                   ` cond* Richard Stallman
@ 2024-01-06 14:33                                                                     ` Ihor Radchenko
  2024-01-06 22:25                                                                       ` [External] : cond* Drew Adams
                                                                                         ` (2 more replies)
  0 siblings, 3 replies; 342+ messages in thread
From: Ihor Radchenko @ 2024-01-06 14:33 UTC (permalink / raw)
  To: rms; +Cc: emacs-devel

Richard Stallman <rms@gnu.org> writes:

>   > I was referring to what "pred" in `pcase' does:
>
>   > ‘(pred FUNCTION)’
>   >      Matches if the predicate FUNCTION returns non-‘nil’ when called on
>   >      EXPVAL.  The test can be negated with the syntax ‘(pred (not
>   >      FUNCTION))’.  The predicate FUNCTION can have one of the following
>   >      forms:
>
> Ok.  Given that for comparison, what conclusion or suggestion to you
> offer about cond*?

From my reading of your latest spec of the cond*, I feel that it is
getting closer and closer to the features provided by `pcase'. The
description is also getting closer to pcase manual page length.

Since cond* is aiming to produce "simpler" syntax compared to pcase, I
feel that the concise style of pcase may either be avoided or considered
carefully. In particular, I believe that (PRED ...) in conf* is no
less confusing than (pred ...) that pcase provides. IMHO, the recursive
(PRED1 (PRED2 ...) ...) is more confusing compared to what pcase offers.

-- 
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] 342+ messages in thread

* RE: [External] : Re: cond*
  2024-01-06 14:33                                                                     ` cond* Ihor Radchenko
@ 2024-01-06 22:25                                                                       ` Drew Adams
  2024-01-08  3:45                                                                         ` Richard Stallman
  2024-01-08  3:47                                                                       ` cond* Richard Stallman
  2024-01-08  3:47                                                                       ` cond* Richard Stallman
  2 siblings, 1 reply; 342+ messages in thread
From: Drew Adams @ 2024-01-06 22:25 UTC (permalink / raw)
  To: Ihor Radchenko, rms@gnu.org; +Cc: emacs-devel@gnu.org

Perhaps off-topic, but I think the difficulty
of human-parsing pcase sexps can be reduced
considerably if each variable bound by the
sexp is clearly shown to be just that.

Even just following a trivial convention,
such as prefixing each variable name with,
`?', would help.

(I'd even suggest that this could be part of
the required syntax - except that pcase is
no longer new and there are lots of pcase
occurrences already out there in the wild.)

Here's an example from bug #68029 (closed as
"done" but really was "wont-fix" -- nothing
was done).  The vars introduced here are
?msg and ?code:

(pcase (get-return-code x)
  ((and (pred stringp) ?msg)
   (message "%s" ?msg))
  ('success       (message "Done!"))
  ('would-block   (message "Sorry, can't do it now"))
  ('read-only     (message "The shmliblick is read-only"))
  ('access-denied (message "You do not have the needed rights"))
  (?code          (message "Unknown return code %S" ?code)))

[ I changed `msg' and `code' in the Elisp
  manual example to `?msg' and `?code', to
  point out that it introduces two variables,
  whereas it was claimed that it introduced
  _NO_ vars and that _therefore_ the pcase
  version was clearer than using `let'.  I
  even used uppercase, `?MSG' and ?CODE, to
  make the presence of the vars clearer.
  
  The doc _still incorrectly claims_ that
  the pcase version is superior because it
  doesn't need to introduce any vars such
  as `code'.  The author and an Emacs
  maintainer, at least, apparently missed
  that pcase binds these variables.  IOW,
  the fact of the var bindings isn't as
  clear as it could be. ]

https://debbugs.gnu.org/cgi/bugreport.cgi?bug=68029#13

^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: [External] : Re: cond*
  2024-01-06 22:25                                                                       ` [External] : cond* Drew Adams
@ 2024-01-08  3:45                                                                         ` Richard Stallman
  2024-01-08 15:20                                                                           ` Drew Adams
  2024-01-09  2:53                                                                           ` map seq and radix-tree-leaf, in pcase Richard Stallman
  0 siblings, 2 replies; 342+ messages in thread
From: Richard Stallman @ 2024-01-08  3:45 UTC (permalink / raw)
  To: Drew Adams; +Cc: yantar92, emacs-devel

[[[ To any NSA and FBI agents reading my email: please consider    ]]]
[[[ whether defending the US Constitution against all enemies,     ]]]
[[[ foreign or domestic, requires you to follow Snowden's example. ]]]

  > Perhaps off-topic, but I think the difficulty
  > of human-parsing pcase sexps can be reduced
  > considerably if each variable bound by the
  > sexp is clearly shown to be just that.

After reading the example, I see the point you're making.
I suppose the same issue could apply to cond*.
Do you think it applies equally to both?
The only pertinent difference is that cond*
would use match* or bind* around constructs that can make bindings.

  > Even just following a trivial convention,
  > such as prefixing each variable name with,
  > `?', would help.

Supposing that cond* could benefit from this idea, how can we make
this idea fit the framework of Emacs Lisp?  `?' has a different
meaning.  Of course, it does not _have_ to take the form of `?', but
what could it be?

-- 
Dr Richard Stallman (https://stallman.org)
Chief GNUisance of the GNU Project (https://gnu.org)
Founder, Free Software Foundation (https://fsf.org)
Internet Hall-of-Famer (https://internethalloffame.org)





^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: cond*
  2024-01-06 14:33                                                                     ` cond* Ihor Radchenko
  2024-01-06 22:25                                                                       ` [External] : cond* Drew Adams
@ 2024-01-08  3:47                                                                       ` Richard Stallman
  2024-01-10 13:03                                                                         ` cond* Ihor Radchenko
  2024-01-08  3:47                                                                       ` cond* Richard Stallman
  2 siblings, 1 reply; 342+ messages in thread
From: Richard Stallman @ 2024-01-08  3:47 UTC (permalink / raw)
  To: Ihor Radchenko; +Cc: emacs-devel

[[[ To any NSA and FBI agents reading my email: please consider    ]]]
[[[ whether defending the US Constitution against all enemies,     ]]]
[[[ foreign or domestic, requires you to follow Snowden's example. ]]]

  > In particular, I believe that (PRED ...) in conf* is no
  > less confusing than (pred ...) that pcase provides.

A few people misunderstood it from the initial version of the
documentation, but that is no reason to think the feature itself
is confusing.

The corresponding pcase `pred' feature is certainly not better -- it
is inside out -- and I don't see any other alternative to try.  If you
would like to suggest one, I'd look at it with interest.

                                                        IMHO, the recursive
  > (PRED1 (PRED2 ...) ...) is more confusing compared to what pcase offers.

You may be right about that.  I decided to remove it, for now.

I introduced a `and' construction which is like the one in pcase.
It can be used for the same purposes and may be more natural.

Thanks for working with me.

-- 
Dr Richard Stallman (https://stallman.org)
Chief GNUisance of the GNU Project (https://gnu.org)
Founder, Free Software Foundation (https://fsf.org)
Internet Hall-of-Famer (https://internethalloffame.org)





^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: cond*
  2024-01-06 14:33                                                                     ` cond* Ihor Radchenko
  2024-01-06 22:25                                                                       ` [External] : cond* Drew Adams
  2024-01-08  3:47                                                                       ` cond* Richard Stallman
@ 2024-01-08  3:47                                                                       ` Richard Stallman
  2024-01-08 15:13                                                                         ` cond* Ihor Radchenko
  2 siblings, 1 reply; 342+ messages in thread
From: Richard Stallman @ 2024-01-08  3:47 UTC (permalink / raw)
  To: Ihor Radchenko; +Cc: emacs-devel

[[[ To any NSA and FBI agents reading my email: please consider    ]]]
[[[ whether defending the US Constitution against all enemies,     ]]]
[[[ foreign or domestic, requires you to follow Snowden's example. ]]]

  > >From my reading of your latest spec of the cond*, I feel that it is
  > getting closer and closer to the features provided by `pcase'. The
  > description is also getting closer to pcase manual page length.

After eliminating the nested constrained variables, it is only 213 lines.

Are there any pcase features that cond* does not provide an equivalent
for?

-- 
Dr Richard Stallman (https://stallman.org)
Chief GNUisance of the GNU Project (https://gnu.org)
Founder, Free Software Foundation (https://fsf.org)
Internet Hall-of-Famer (https://internethalloffame.org)





^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: cond*
  2024-01-06 13:09                                                                     ` cond* Ihor Radchenko
@ 2024-01-08  3:47                                                                       ` Richard Stallman
  2024-01-08 15:26                                                                         ` cond* Ihor Radchenko
  0 siblings, 1 reply; 342+ messages in thread
From: Richard Stallman @ 2024-01-08  3:47 UTC (permalink / raw)
  To: Ihor Radchenko; +Cc: emacs-devel

[[[ To any NSA and FBI agents reading my email: please consider    ]]]
[[[ whether defending the US Constitution against all enemies,     ]]]
[[[ foreign or domestic, requires you to follow Snowden's example. ]]]

  > May you please elaborate how you see named variables in `rx'?

Exactly the same as in `rx' in pcase.

I suppose pcase transforms the (rx ...) construct into a regular
expression -- right?  If this can be implemented for the (rx ...)
pattern in pcase, it can be implemented for `rx' the function with the
same code -- right?

I expect it would work by allocating a subpattern number for each
(let ...) variable.

Please don't tell me that someone reimplemented `rx' from scratch
for pcase, rather than using the existing `rx' code!

-- 
Dr Richard Stallman (https://stallman.org)
Chief GNUisance of the GNU Project (https://gnu.org)
Founder, Free Software Foundation (https://fsf.org)
Internet Hall-of-Famer (https://internethalloffame.org)





^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: cond*
  2024-01-06 13:13                                                                     ` cond* Ihor Radchenko
@ 2024-01-08  3:47                                                                       ` Richard Stallman
  2024-01-08 15:35                                                                         ` cond* Ihor Radchenko
  0 siblings, 1 reply; 342+ messages in thread
From: Richard Stallman @ 2024-01-08  3:47 UTC (permalink / raw)
  To: Ihor Radchenko; +Cc: emacs-devel

[[[ To any NSA and FBI agents reading my email: please consider    ]]]
[[[ whether defending the US Constitution against all enemies,     ]]]
[[[ foreign or domestic, requires you to follow Snowden's example. ]]]

  > > Since the idea is pattern-matching, I think that a regexp is natural
  > > as well as more general.  Why not do this?

  > It is not very clear then how to match plain strings for equality.

1. Instead of writing the string as a literal, write a regexp to match
only that string.  This is not hard.

2. Use this constrained variable patern:

   (equal foo "xyz")

It will bind the variable `foo', but you are not required to use it.

-- 
Dr Richard Stallman (https://stallman.org)
Chief GNUisance of the GNU Project (https://gnu.org)
Founder, Free Software Foundation (https://fsf.org)
Internet Hall-of-Famer (https://internethalloffame.org)





^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: Instead of pcase
  2024-01-06 13:04                                                                 ` Ihor Radchenko
@ 2024-01-08  3:47                                                                   ` Richard Stallman
  2024-01-08 15:42                                                                     ` Ihor Radchenko
  0 siblings, 1 reply; 342+ messages in thread
From: Richard Stallman @ 2024-01-08  3:47 UTC (permalink / raw)
  To: Ihor Radchenko; +Cc: emacs-devel

[[[ To any NSA and FBI agents reading my email: please consider    ]]]
[[[ whether defending the US Constitution against all enemies,     ]]]
[[[ foreign or domestic, requires you to follow Snowden's example. ]]]

  > > I wonder why people defined `xor'.  It can't be used
  > > as a conditional, like `and' and `or', so what is the point of it?

  > `xor' can be used as conditional

Perhaps we are miscommunicating.

`or' and `and' can act as conditionals.  (and X Y) says to
do Y if X is true.  (or X Y) says to do Y if X is false.
That is why those constructs are useful.

`xor' can'e be used as a conditional, because all of the arguments of
`xor' must always be evaluatedd.


-- 
Dr Richard Stallman (https://stallman.org)
Chief GNUisance of the GNU Project (https://gnu.org)
Founder, Free Software Foundation (https://fsf.org)
Internet Hall-of-Famer (https://internethalloffame.org)





^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: cond*
  2024-01-08  3:47                                                                       ` cond* Richard Stallman
@ 2024-01-08 15:13                                                                         ` Ihor Radchenko
  2024-01-27  3:37                                                                           ` cond* Richard Stallman
  0 siblings, 1 reply; 342+ messages in thread
From: Ihor Radchenko @ 2024-01-08 15:13 UTC (permalink / raw)
  To: rms; +Cc: emacs-devel

Richard Stallman <rms@gnu.org> writes:

>   > >From my reading of your latest spec of the cond*, I feel that it is
>   > getting closer and closer to the features provided by `pcase'. The
>   > description is also getting closer to pcase manual page length.
>
> After eliminating the nested constrained variables, it is only 213 lines.
>
> Are there any pcase features that cond* does not provide an equivalent
> for?

Other than rx, one missing feature is an ability to match against
multiple values in a single condition:

(defun yant/list-sum (list)
  (apply #'+ list))
(pcase '(1 2 3)
  ((and `(,x ,y ,z) (app yant/list-sum (and sum (guard (< 2 sum)))))
   (format "%d + %d + %d = %d; 2 is < %d" x y z sum sum)))
; => "1 + 2 + 3 = 6; 2 is < 6"   

In the above, we first match `(,x ,y ,z) against '(1 2 3) and then
match (and sum (guard (< 2 sum))) against the result of (yant/list-sum '(1 2 3))

Also, `pcase' performs some compiler-like optimizations on the provided
patterns.

-- 
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] 342+ messages in thread

* RE: [External] : Re: cond*
  2024-01-08  3:45                                                                         ` Richard Stallman
@ 2024-01-08 15:20                                                                           ` Drew Adams
  2024-01-09  2:53                                                                           ` map seq and radix-tree-leaf, in pcase Richard Stallman
  1 sibling, 0 replies; 342+ messages in thread
From: Drew Adams @ 2024-01-08 15:20 UTC (permalink / raw)
  To: rms@gnu.org; +Cc: yantar92@posteo.net, emacs-devel@gnu.org

> > Perhaps off-topic, but I think the difficulty
> > of human-parsing pcase sexps can be reduced
> > considerably if each variable bound by the
> > sexp is clearly shown to be just that.
> 
> After reading the example, I see the point you're making.
> I suppose the same issue could apply to cond*.
> Do you think it applies equally to both?
> The only pertinent difference is that cond*
> would use match* or bind* around constructs that can make bindings.

My point about pcase was made originally in
the context of (IMHO) poor examples in the
Elisp manual.

I've only cursorily followed this cond* thread.
My point about pcase not signalling well that
something is a variable binding may not apply
to cond*, if variabless in cond* are always
introduced with a label that signals a binding.
That's akin to the use of an explicit "let" to
signal bindings - not a problem.

> > Even just following a trivial convention,
> > such as prefixing each variable name with,
> > `?', would help.
> 
> Supposing that cond* could benefit from this idea, how can we make
> this idea fit the framework of Emacs Lisp?  `?' has a different
> meaning.  Of course, it does not _have_ to take the form of `?', but
> what could it be?

I don't know.  Some Lisp pattern-matching
contexts have used a cons such as `(? VAR)'
(instead of just `?VAR') to indicate a
variable `VAR'.  And in some such contexts,
the cons can even be updated destructively
to unify (logic programming) or instantiate.

My guess is that if you use a label such as
`match*' or `bind*', and if in that context
it's clear enough which things are the vars,
then you don't also need a syntax convention
(or enforcement) such as a `?' prefix.

So my comment about this may be off-topic in
a strict sense for this thread.  In a more
general way it might still be relevant or
helpful.

I really do guess that much of the bother
people have with pcase and learning its
syntax comes from _vars not being obvious_.

For lispers used to backquote syntax I
think variables not signaling themselves
is likely to be more of an obstacle than
the use of backquote.

A third obstacle, IMO, is the mixing of
variable-binding constructs with control
(conditional) constructs.  That's also
the case for `loop' and even things like
`if-let'.  But `if-let' & compagnie are
simple, compared to `loop' and `pcase'.

Among (1) unobvious var bindings, (2)
backquote syntax, and (3) mixing of
control structure with pattern-matching
/ var-binding, the degree to which each
presents an obstacle to understanding/
reading/learning is debatable.

^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: cond*
  2024-01-08  3:47                                                                       ` cond* Richard Stallman
@ 2024-01-08 15:26                                                                         ` Ihor Radchenko
  2024-01-27  3:37                                                                           ` cond* Richard Stallman
  0 siblings, 1 reply; 342+ messages in thread
From: Ihor Radchenko @ 2024-01-08 15:26 UTC (permalink / raw)
  To: rms; +Cc: emacs-devel

Richard Stallman <rms@gnu.org> writes:

>   > May you please elaborate how you see named variables in `rx'?
>
> Exactly the same as in `rx' in pcase.
>
> I suppose pcase transforms the (rx ...) construct into a regular
> expression -- right?  If this can be implemented for the (rx ...)
> pattern in pcase, it can be implemented for `rx' the function with the
> same code -- right?
>
> I expect it would work by allocating a subpattern number for each
> (let ...) variable.
>
> Please don't tell me that someone reimplemented `rx' from scratch
> for pcase, rather than using the existing `rx' code!

The way (let ...) expressions are handled inside pcase is defined in
`rx--pcase-expand'. It has nothing to do with rx operation itself.
Instead, it parser the rx pattern, and transforms it into a different
pcase match:

This
(pcase "  #+begin: something"
  ((rx line-start (0+ (any " \t")) "#+BEGIN:" (0+ (any " \t"))
     ;; matches "something"
     ;; (let VAR <sub-expression>) binds VAR to sub-expression match.
     (let matched-value (1+ word)))
   (format "We just matched \"%s\"" matched-value)))

becomes something along the lines of

(pcase "  #+begin: something"
  ((app (lambda (s)
          (and (string-match regexp-generated-by-rx s)
               (list (match-string 0 s)
                     (match-string 1 s))))
        `(_ ,matched-value))

In other words, `rx' pattern matching is implemented by rewriting the
pattern using other `pcase' constructs during macro expansion. The
original `rx' is not changed and does not assign any variables.

-- 
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] 342+ messages in thread

* Re: cond*
  2024-01-08  3:47                                                                       ` cond* Richard Stallman
@ 2024-01-08 15:35                                                                         ` Ihor Radchenko
  0 siblings, 0 replies; 342+ messages in thread
From: Ihor Radchenko @ 2024-01-08 15:35 UTC (permalink / raw)
  To: rms; +Cc: emacs-devel

Richard Stallman <rms@gnu.org> writes:

>   > > Since the idea is pattern-matching, I think that a regexp is natural
>   > > as well as more general.  Why not do this?
>
>   > It is not very clear then how to match plain strings for equality.
>
> 1. Instead of writing the string as a literal, write a regexp to match
> only that string.  This is not hard.

This is a bad idea when writing _generic purpose_ code - regexp matching
is _a lot_ slower compared to string comparison. Orders of magnitude.

> 2. Use this constrained variable patern:
>
>    (equal foo "xyz")
>
> It will bind the variable `foo', but you are not required to use it.

I am not a big fan of introducing yet another convention:

Compare

(cond*
 ((match* `("foo?" "bar") '("fo" "bar")) t)) ; => t

(pcase '("fo" "bar")
  (`("foo?" "bar") t)) ; => nil

People familiar with `pcase' will have to keep the above distinction in
mind all the time - a source of potential confusion.

-- 
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] 342+ messages in thread

* Re: Instead of pcase
  2024-01-08  3:47                                                                   ` Richard Stallman
@ 2024-01-08 15:42                                                                     ` Ihor Radchenko
  2024-01-27  3:37                                                                       ` Richard Stallman
  0 siblings, 1 reply; 342+ messages in thread
From: Ihor Radchenko @ 2024-01-08 15:42 UTC (permalink / raw)
  To: rms; +Cc: emacs-devel

Richard Stallman <rms@gnu.org> writes:

>   > > I wonder why people defined `xor'.  It can't be used
>   > > as a conditional, like `and' and `or', so what is the point of it?
>
>   > `xor' can be used as conditional
>
> Perhaps we are miscommunicating.
>
> `or' and `and' can act as conditionals.  (and X Y) says to
> do Y if X is true.  (or X Y) says to do Y if X is false.
> That is why those constructs are useful.

IMHO, it is a better practice to do code flow control via special forms
like `if', `when', `prog1', `progn', etc.

In my mind, `or' and `and' are to be used as function (they are, indeed,
functions). Treating them as flow control constructs may lead to
confusion, as it did for you.

> `xor' can'e be used as a conditional, because all of the arguments of
> `xor' must always be evaluatedd.

`xor' is a function - in cond*, PRED may be any function. And the fact
that not all the arguments are evaluated in (PRED x arg1 arg2 ...) is
the source of my confusion and the reason why I objected the idea of
PRED in its current form when "x" not visually distinct from the rest of
the arguments.

-- 
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] 342+ messages in thread

* map seq and radix-tree-leaf, in pcase
  2024-01-08  3:45                                                                         ` Richard Stallman
  2024-01-08 15:20                                                                           ` Drew Adams
@ 2024-01-09  2:53                                                                           ` Richard Stallman
  1 sibling, 0 replies; 342+ messages in thread
From: Richard Stallman @ 2024-01-09  2:53 UTC (permalink / raw)
  To: emacs-devel

[[[ To any NSA and FBI agents reading my email: please consider    ]]]
[[[ whether defending the US Constitution against all enemies,     ]]]
[[[ foreign or domestic, requires you to follow Snowden's example. ]]]

In the help text for pcase, I saw information about these three
constructs, but I am not sure what they mean.

    -- (map &rest ARGS)

    -- (seq &rest PATTERNS)

    -- (radix-tree-leaf VPAT)

Perhaps I should add similar constructs, or substitutes for them, to
cond*.  Could someone please explain what they mean, and give an
explained example?

-- 
Dr Richard Stallman (https://stallman.org)
Chief GNUisance of the GNU Project (https://gnu.org)
Founder, Free Software Foundation (https://fsf.org)
Internet Hall-of-Famer (https://internethalloffame.org)





^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: Instead of pcase
  2023-12-01 10:02                             ` João Távora
  2023-12-01 11:52                               ` Eli Zaretskii
@ 2024-01-09  5:33                               ` Stefan Kangas
  2024-01-09 10:43                                 ` João Távora
  1 sibling, 1 reply; 342+ messages in thread
From: Stefan Kangas @ 2024-01-09  5:33 UTC (permalink / raw)
  To: João Távora, Eli Zaretskii
  Cc: owinebar, rms, dmitry, philipk, emacs-devel

João Távora <joaotavora@gmail.com> writes:

> It is _easy_ to explain that "scary" construct _if_ you learn to _lean_
> on what should be probably existing knowledge.  No doc-consulting
> necessary.
>
> You take a backtick-starting construct with as many scary periods
> things as you can find and then, say
>
> `(,foo . (,bar . ,baz))
>
> And then ask yourself: "what kind of list does this build if I just
> let-bind foo, bar and baz to 42?". And then you answer yourself
> "Why, it's the improper list (42 42 . 42) made up of just two cons
> cells and 3 fixnums!".  So _that's_ the kind of list that can be
> destructured with the pcase expression.
>
> This solves the reading problem.  Now the writing problem. To author
> new pcase patterns one uses more or less the same process.  One again
> leans on one's existing knowledge of how the list structure would be
> expressed with backtick-and-quote.  So once you know the list
> structure in your mind you write it as a backtick-and-quote expression,
> just as if you were going to craft that list (though you aren't of
> course).  Then once you're happy with your expression, you may take it
> and you put it in one of the BINDINGS left-hand part of a 'let'.
> Then you rename that 'let' to 'pcase-let' and away you go!

Could you reformat this as a documentation patch?



^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: Instead of pcase
  2023-12-01 18:45                                       ` João Távora
@ 2024-01-09  5:36                                         ` Stefan Kangas
  0 siblings, 0 replies; 342+ messages in thread
From: Stefan Kangas @ 2024-01-09  5:36 UTC (permalink / raw)
  To: João Távora, Dmitry Gutov
  Cc: Eli Zaretskii, owinebar, rms, philipk, emacs-devel

João Távora <joaotavora@gmail.com> writes:

> On Fri, Dec 1, 2023 at 6:28 PM Dmitry Gutov <dmitry@gutov.dev> wrote:
>
>> That just reaffirms my understanding that the main problem with 'pcase'
>> that we have is documentation. The nodes are written very bottom-up,
>> whereas what's really needed for someone to understand the core usage,
>> would look more like the first half of the node "Destructuring with
>> ‘pcase’ Patterns".
>
> +1
>
> Instead of "11.4 Pattern-Matching Conditional", that section could
> be called "Pcase and friends" or "The pcase family of macros family".
>
> Though it is original use of pcase, pcase conditionals are just one
> of the things you can do with it, and in my recent experience, not
> necessarily the most common or useful one.  Also 'pcase-let' is
> probably easier to understand than 'pcase', as it only does
> destructuring and binding whereas the other macros do that and something
> more on top.
>
> Besides renaming, that section could start with a 11.4.1 "quick-start"
> with some brief explanation about how pcase relates to backquote-and-tick
> and with an example for 'pcase-let', not unlike the one that surfaced here.
>
> If space allows,  an example for 'pcase' that introduces the conditional
> macro can be added.

Please reformat this also as documentation patches and send to the bug
tracker.



^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: Instead of pcase
  2024-01-09  5:33                               ` Stefan Kangas
@ 2024-01-09 10:43                                 ` João Távora
  0 siblings, 0 replies; 342+ messages in thread
From: João Távora @ 2024-01-09 10:43 UTC (permalink / raw)
  To: Stefan Kangas; +Cc: Eli Zaretskii, owinebar, rms, dmitry, philipk, emacs-devel

On Tue, Jan 9, 2024 at 5:33 AM Stefan Kangas <stefankangas@gmail.com> wrote:

> > You take a backtick-starting construct with as many scary periods
> > things as you can find and then, say
> >
> > `(,foo . (,bar . ,baz))
> >
> > And then ask yourself: "what kind of list does this build if I just
> > let-bind foo, bar and baz to 42?". And then you answer yourself
> > "Why, it's the improper list (42 42 . 42) made up of just two cons
> > cells and 3 fixnums!".  So _that's_ the kind of list that can be
> > destructured with the pcase expression.
> >
> > This solves the reading problem.  Now the writing problem. To author
> > new pcase patterns one uses more or less the same process.  One again
> > leans on one's existing knowledge of how the list structure would be
> > expressed with backtick-and-quote.  So once you know the list
> > structure in your mind you write it as a backtick-and-quote expression,
> > just as if you were going to craft that list (though you aren't of
> > course).  Then once you're happy with your expression, you may take it
> > and you put it in one of the BINDINGS left-hand part of a 'let'.
> > Then you rename that 'let' to 'pcase-let' and away you go!
>
> Could you reformat this as a documentation patch?

TL;DR: Maybe I will do that "if noone beats me to it" (TM).

All the ideas I had to share are already there and free to use.
If you find these ideas useful or their exposition elegant,
I'm flattered :-)  but there's still the work of finding the correct spot
in the pcase documentation where they would fit better and
identifying what other parts of that doc they now supersede, so
that a cohesive whole can be achieved.

This is usually the most difficult part of adding to existing
documentation (very similar to maintaining code, actually).
Then there are more minor stylistic and formatting issues, but
these are still some effort.

I don't have the resources to do this work right now, and
properly coordinate with other people updating other parts of
that documentation.

João



^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: cond*
  2024-01-08  3:47                                                                       ` cond* Richard Stallman
@ 2024-01-10 13:03                                                                         ` Ihor Radchenko
  2024-01-13  3:50                                                                           ` cond* Richard Stallman
  0 siblings, 1 reply; 342+ messages in thread
From: Ihor Radchenko @ 2024-01-10 13:03 UTC (permalink / raw)
  To: rms; +Cc: emacs-devel

Richard Stallman <rms@gnu.org> writes:

>   > In particular, I believe that (PRED ...) in conf* is no
>   > less confusing than (pred ...) that pcase provides.
>
> A few people misunderstood it from the initial version of the
> documentation, but that is no reason to think the feature itself
> is confusing.
>
> The corresponding pcase `pred' feature is certainly not better -- it
> is inside out -- and I don't see any other alternative to try.  If you
> would like to suggest one, I'd look at it with interest.

My suggestion is simple - drop PRED and just leave "constrain".
This will be more verbose, but also more clear.

-- 
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] 342+ messages in thread

* Re: cond*
  2024-01-10 13:03                                                                         ` cond* Ihor Radchenko
@ 2024-01-13  3:50                                                                           ` Richard Stallman
  2024-01-13  6:32                                                                             ` cond* Adam Porter
  2024-01-13 19:47                                                                             ` cond* Ihor Radchenko
  0 siblings, 2 replies; 342+ messages in thread
From: Richard Stallman @ 2024-01-13  3:50 UTC (permalink / raw)
  To: Ihor Radchenko; +Cc: emacs-devel

[[[ To any NSA and FBI agents reading my email: please consider    ]]]
[[[ whether defending the US Constitution against all enemies,     ]]]
[[[ foreign or domestic, requires you to follow Snowden's example. ]]]

(symbolp x) is simpler and more natural than the pcase equivalent,
which I believe would be (and (pred symbolp) x).  People seem to have
accepted the latter, without criticizing it as unnatural.  I think
they will accept (symbolp x) also.  I think that people will get used
to this once they start actually using cond*.

To require use of the more complex `constrain' form even for the
common simple cases would make cond* less convenient for real.  I
don't think it would be wise to create a real drawback to eliminate a
mere perception of a drawback.

-- 
Dr Richard Stallman (https://stallman.org)
Chief GNUisance of the GNU Project (https://gnu.org)
Founder, Free Software Foundation (https://fsf.org)
Internet Hall-of-Famer (https://internethalloffame.org)





^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: cond*
  2024-01-13  3:50                                                                           ` cond* Richard Stallman
@ 2024-01-13  6:32                                                                             ` Adam Porter
  2024-01-16  3:31                                                                               ` cond* Richard Stallman
  2024-01-13 19:47                                                                             ` cond* Ihor Radchenko
  1 sibling, 1 reply; 342+ messages in thread
From: Adam Porter @ 2024-01-13  6:32 UTC (permalink / raw)
  To: rms; +Cc: emacs-devel, yantar92

> (symbolp x) is simpler and more natural than the pcase equivalent,
> which I believe would be (and (pred symbolp) x).  People seem to have
> accepted the latter, without criticizing it as unnatural.  

I think that is an apples-to-oranges comparison.  This pcase form:

   (and (pred symbolp) x)

is specifically a pcase form.  It does two things, and--crucially--it 
does them separately and explicitly:

1. It tests the EXP with the predicate `symbolp'.
2. If the test is non-nil, it binds the EXP to `x'.

The list `(pred symbolp)' is obviously not a normal expression, because 
`symbolp' is a predicate function and is unquoted in this list (i.e. 
there is no `symbolp' variable bound).

In contrast, this cond* form:

   (symbolp x)

looks like a normal expression calling the function `symbolp'; and, in a 
sense, it is, because that will happen.  But that same form also binds 
the variable `x' after testing its to-be-bound value with the predicate 
`symbolp'--yet the binding is not explicit and separate, but implicit 
and combined.

Contrast that also with a pcase `guard' form, like in:

   (and x (guard (symbolp x)))

That also does the same thing, but again, the binding and testing are 
separate and explicit.  And it provides the additional benefit of the 
`guard' form being a normal expression, so it could include other parts, 
like:

   (and x (guard (and (symbolp x)
                      (string-prefix-p "foo" (symbol-name x)))))

ISTM that the most potentially confusing aspect of that pcase form is 
that `and' is effectively used to denote binding; and I think that could 
be mitigated by offering an alternative, optional keyword to surround 
bindings, to make them appear more explicit.

> I think they will accept (symbolp x) also.  I think that people will
> get used to this once they start actually using cond*.

By the same token, people could get used to pcase's design once they 
start using it.  But pcase's binding and testing forms are more explicit 
and look less like normal expressions, which makes it potentially less 
confusing to users.

We often bemoan the addition of various libraries to Emacs and ELPA that 
seem to do what existing ones already do, but in slightly different 
ways.  Why not improve pcase to solve these minor shortcomings, instead 
of adding another library that does some similar things, in slightly 
different, incompatible ways, while not even offering as much 
functionality as pcase?  (e.g. as I've mentioned, pcase can destructure 
maps, structs, and EIEIO objects, and is extensible by other 
libraries--it's an incredible tool that I sorely miss when working in 
environments outside of Emacs Lisp.)

--Adam



^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: cond*
  2024-01-13  3:50                                                                           ` cond* Richard Stallman
  2024-01-13  6:32                                                                             ` cond* Adam Porter
@ 2024-01-13 19:47                                                                             ` Ihor Radchenko
  2024-01-15  3:13                                                                               ` cond* Richard Stallman
  1 sibling, 1 reply; 342+ messages in thread
From: Ihor Radchenko @ 2024-01-13 19:47 UTC (permalink / raw)
  To: rms; +Cc: emacs-devel

Richard Stallman <rms@gnu.org> writes:

> ...  I think
> they will accept (symbolp x) also.  I think that people will get used
> to this once they start actually using cond*.

People may as well get used to `pcase'.
But `cond*' is supposed to be _better_ than `pcase', isn't it?
Otherwise, we will end up not with one, but two confusing pattern
matching macros and people will have to learn both.

> To require use of the more complex `constrain' form even for the
> common simple cases would make cond* less convenient for real.  I
> don't think it would be wise to create a real drawback to eliminate a
> mere perception of a drawback.

I was confused when reading the examples you provided. Same for Adam.
So, at least two people are confused - it is not a "mere perception".

I tried to come up with some better notation that is not as verbose as
"constrain", but I cannot think of anything less confusing,
unfortunately.

-- 
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] 342+ messages in thread

* Re: cond*
  2024-01-13 19:47                                                                             ` cond* Ihor Radchenko
@ 2024-01-15  3:13                                                                               ` Richard Stallman
  0 siblings, 0 replies; 342+ messages in thread
From: Richard Stallman @ 2024-01-15  3:13 UTC (permalink / raw)
  To: Ihor Radchenko; +Cc: emacs-devel

[[[ To any NSA and FBI agents reading my email: please consider    ]]]
[[[ whether defending the US Constitution against all enemies,     ]]]
[[[ foreign or domestic, requires you to follow Snowden's example. ]]]

  > I was confused when reading the examples you provided. Same for Adam.
  > So, at least two people are confused - it is not a "mere perception".

I think that with better documentation, containing good examples
explained, and seeing it in use, people will get used to it and like
it.

When the pcase form  (and (pred symbolp) x)  and the cond* form
(symbolp x)  are competing pm an equal footing, I think people
will prefer the brevity of the cond* form.  But we will see.
--
-- 
Dr Richard Stallman (https://stallman.org)
Chief GNUisance of the GNU Project (https://gnu.org)
Founder, Free Software Foundation (https://fsf.org)
Internet Hall-of-Famer (https://internethalloffame.org)





^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: cond*
  2024-01-13  6:32                                                                             ` cond* Adam Porter
@ 2024-01-16  3:31                                                                               ` Richard Stallman
  0 siblings, 0 replies; 342+ messages in thread
From: Richard Stallman @ 2024-01-16  3:31 UTC (permalink / raw)
  To: Adam Porter; +Cc: emacs-devel, yantar92

[[[ To any NSA and FBI agents reading my email: please consider    ]]]
[[[ whether defending the US Constitution against all enemies,     ]]]
[[[ foreign or domestic, requires you to follow Snowden's example. ]]]

  > In contrast, this cond* form:

  >    (symbolp x)

  > looks like a normal expression calling the function `symbolp'; 

This is in the match* construct, whose operands are never Lisp
expressions.  Just as inaide pcase, people will understand these are
different.  People will be accustomed to seeing cond* patterns there,
just as people who use ocase are accustomed to seeing pcase patterns
there.

    and, in a 
  > sense, it is, because that will happen.

No, that's not quite correct.  What it does is test the value there in
the data to see if it is symbolp, and if so, the match will bind x to
that symbol.

It is similar to what happens if the pattern is just

   x

You're working hard to convince people that they they will dislike
cond*.  But that is not a usefu thing to do.  Soon people will have a
chance to play with cond* and see what they think.

-- 
Dr Richard Stallman (https://stallman.org)
Chief GNUisance of the GNU Project (https://gnu.org)
Founder, Free Software Foundation (https://fsf.org)
Internet Hall-of-Famer (https://internethalloffame.org)





^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: cond*
  2024-01-08 15:13                                                                         ` cond* Ihor Radchenko
@ 2024-01-27  3:37                                                                           ` Richard Stallman
  2024-02-01 16:26                                                                             ` cond* Ihor Radchenko
  0 siblings, 1 reply; 342+ messages in thread
From: Richard Stallman @ 2024-01-27  3:37 UTC (permalink / raw)
  To: Ihor Radchenko; +Cc: emacs-devel

[[[ To any NSA and FBI agents reading my email: please consider    ]]]
[[[ whether defending the US Constitution against all enemies,     ]]]
[[[ foreign or domestic, requires you to follow Snowden's example. ]]]

  > Other than rx, one missing feature is an ability to match against
  > multiple values in a single condition:
  > (defun yant/list-sum (list)
  >   (apply #'+ list))
  > (pcase '(1 2 3)
  >   ((and `(,x ,y ,z) (app yant/list-sum (and sum (guard (< 2 sum)))))
  >    (format "%d + %d + %d = %d; 2 is < %d" x y z sum sum)))
  > ; => "1 + 2 + 3 = 6; 2 is < 6"   

Understanding this was a struggle, but I think it can be done with

  (cond* ((match* `(,x ,y ,z) list-of-three))
         ((< 2 (+ x y z))
          success)))

It is not the one condition which is the goal you specified, but given
the flexibility of cond* it doesn't need to be one condition.  And it
is much clearer than the pcase code to do the same job.


-- 
Dr Richard Stallman (https://stallman.org)
Chief GNUisance of the GNU Project (https://gnu.org)
Founder, Free Software Foundation (https://fsf.org)
Internet Hall-of-Famer (https://internethalloffame.org)





^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: cond*
  2024-01-08 15:26                                                                         ` cond* Ihor Radchenko
@ 2024-01-27  3:37                                                                           ` Richard Stallman
  0 siblings, 0 replies; 342+ messages in thread
From: Richard Stallman @ 2024-01-27  3:37 UTC (permalink / raw)
  To: Ihor Radchenko; +Cc: emacs-devel

[[[ To any NSA and FBI agents reading my email: please consider    ]]]
[[[ whether defending the US Constitution against all enemies,     ]]]
[[[ foreign or domestic, requires you to follow Snowden's example. ]]]

  > The way (let ...) expressions are handled inside pcase is defined in
  > `rx--pcase-expand'. It has nothing to do with rx operation itself.

How surprising.

I judt called one of the entry points of rx, and it seems to work.

-- 
Dr Richard Stallman (https://stallman.org)
Chief GNUisance of the GNU Project (https://gnu.org)
Founder, Free Software Foundation (https://fsf.org)
Internet Hall-of-Famer (https://internethalloffame.org)





^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: Instead of pcase
  2024-01-08 15:42                                                                     ` Ihor Radchenko
@ 2024-01-27  3:37                                                                       ` Richard Stallman
  0 siblings, 0 replies; 342+ messages in thread
From: Richard Stallman @ 2024-01-27  3:37 UTC (permalink / raw)
  To: Ihor Radchenko; +Cc: emacs-devel

[[[ To any NSA and FBI agents reading my email: please consider    ]]]
[[[ whether defending the US Constitution against all enemies,     ]]]
[[[ foreign or domestic, requires you to follow Snowden's example. ]]]

  > In my mind, `or' and `and' are to be used as function (they are, indeed,
  > functions).

They are not Lisp functions -- they are implemented as special forms,
so as not to always compute all their arguments.
That's what makes them useful.

What puzzled me about having a function called `xor' is that it is
merely an ordinary function on truth values, thus NOT simplar in its use
to `and' and `or'.


-- 
Dr Richard Stallman (https://stallman.org)
Chief GNUisance of the GNU Project (https://gnu.org)
Founder, Free Software Foundation (https://fsf.org)
Internet Hall-of-Famer (https://internethalloffame.org)





^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: cond*
  2024-01-27  3:37                                                                           ` cond* Richard Stallman
@ 2024-02-01 16:26                                                                             ` Ihor Radchenko
  2024-02-03  3:36                                                                               ` cond* Richard Stallman
  0 siblings, 1 reply; 342+ messages in thread
From: Ihor Radchenko @ 2024-02-01 16:26 UTC (permalink / raw)
  To: rms; +Cc: emacs-devel

Richard Stallman <rms@gnu.org> writes:

>   > Other than rx, one missing feature is an ability to match against
>   > multiple values in a single condition:
>   > (defun yant/list-sum (list)
>   >   (apply #'+ list))
>   > (pcase '(1 2 3)
>   >   ((and `(,x ,y ,z) (app yant/list-sum (and sum (guard (< 2 sum)))))
>   >    (format "%d + %d + %d = %d; 2 is < %d" x y z sum sum)))
>   > ; => "1 + 2 + 3 = 6; 2 is < 6"   
>
> Understanding this was a struggle, but I think it can be done with
>
>   (cond* ((match* `(,x ,y ,z) list-of-three))
>          ((< 2 (+ x y z))
>           success)))

Nope.

Consider

(let ((list-of-three '(1 2)))
  (cond* ((match* `(,x ,y ,z) list-of-three))
         ((< 2 (+ x y z))
          'success))) ; => (wrong-type-argument number-or-marker-p nil)

Debugger entered--Lisp error: (wrong-type-argument number-or-marker-p nil)
  (+ 1 2 nil)
  (< 2 (+ x y z))
  (if (< 2 (+ x y z)) (progn 'success))
  (let* ((z (nth 2 d2495))...

I used the latest version of cond* you submitted in
https://yhetil.org/emacs-devel/86cytg1vcu.fsf@gnu.org/T/#t

Also, I was surprised by

(let ((list-of-three '(1 2 3 4)))
  (cond* ((match* `(,x ,y ,z) list-of-three))
         ((< 2 (+ x y z))
          'success))) ; => success

I did not expect list of four to match `(,x ,y ,z).

-- 
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] 342+ messages in thread

* Re: cond*
  2024-02-01 16:26                                                                             ` cond* Ihor Radchenko
@ 2024-02-03  3:36                                                                               ` Richard Stallman
  2024-02-03 16:52                                                                                 ` cond* Ihor Radchenko
  0 siblings, 1 reply; 342+ messages in thread
From: Richard Stallman @ 2024-02-03  3:36 UTC (permalink / raw)
  To: Ihor Radchenko; +Cc: emacs-devel

[[[ To any NSA and FBI agents reading my email: please consider    ]]]
[[[ whether defending the US Constitution against all enemies,     ]]]
[[[ foreign or domestic, requires you to follow Snowden's example. ]]]

  > (let ((list-of-three '(1 2)))
  >   (cond* ((match* `(,x ,y ,z) list-of-three))
  >          ((< 2 (+ x y z))
  >           'success))) ; => (wrong-type-argument number-or-marker-p nil)

That is not exactly a bug, but it is an unclarity in the design.

The match* condition fails, but since it is a non-exit clause, that
failure doesn't affect anything -- it goes ahead an executes the next
clause.  Arguably it is doing exactly what your code said.

But it raises the question of what a non-exit match* clause should do
when it does not match.  What do you think it should do?

The idea that occurs to me is this: bind all those variables,
initializing by matching those that can match, and initializing the
rest to nil.

-- 
Dr Richard Stallman (https://stallman.org)
Chief GNUisance of the GNU Project (https://gnu.org)
Founder, Free Software Foundation (https://fsf.org)
Internet Hall-of-Famer (https://internethalloffame.org)





^ permalink raw reply	[flat|nested] 342+ messages in thread

* Re: cond*
  2024-02-03  3:36