The poor state of documentation of pcase like things.

classic Classic list List threaded Threaded
374 messages Options
1234 ... 19
Reply | Threaded
Open this post in threaded view
|

The poor state of documentation of pcase like things.

Alan Mackenzie
Hello, Emacs.

Months after recognising that the documentation of pcase like things is
in need of vast improvement, we haven't advanced significantly.

We appear to have the following functions/macros: pcase, pcase-let,
pcase-let*, pcase-codegen, pcase-defmacro, pcase-dolist,
pcase-exhaustive, and pcase-lambda.

NONE OF THESE, with the exception of pcase itself, IS EVEN MENTIONED IN
THE ELISP MANUAL.

NONE OF THESE, with the exception of pcase itself, HAS A MEANINGFUL DOC
STRING.

Some of these doc strings are patronising indeed.  They all seem to say,
implicitly, "the author's time is far too valuable to waste in writing
meaningful documentation".

Particularly egregious is the doc string for pcase-exhaustive: "The
exhaustive version of `pcase' (which see).".  Uhh????  Needless to say,
the doc string of pcase makes no mention of "exhaustive".

Let us analyse the documentation of the one macro which is documented to
any meaningful extent, pcase itself:

The article in the Elisp manual for pcase starts well, documenting the
basic form and outlining the basic semantics, but then starts rambling
on like a tutorial, rather than filling in the semantic details.  Here
is a partial list of what is missing from that manual page:

(i) A @dfn{U-PATTERN}.
(ii) A @dfn{Q-PATTERN}.
These two things are described only in terms of their structure, not
what they are conceptually.  What do "U" and "Q" stand for?  What is the
semantic significance of a Q-PATTERN?
(iii) A statement that ` is not ` and , is not ,.
(iv) A rigorous specification of what ` and , (and ,@?) mean in pcase
patterns.
(v) A rigorous specification of when variables get bound, and what they
get bound to.
(vi) A rigorous specification of when a value matches a pattern.

Now, let's have a look a pcase's doc string.  It doesn't say what pcase
does: "perform ML-style pattern matching" is meaningless to anybody who
doesn't know ML-style pattern matching.  What it should say is that the
value is used to select (at most) one of the CASES, and the forms in
that CASE are evaluated - or something like that.

It would appear that Lisp programmers are expected to absorb the
semantics (and sometimes even the syntax) of pcase-* by osmosis:
studying and imitating examples.  This is a Bad Thing.

Most (?all) of the rest of Emacs Lisp is effectively and rigorously
documented.  For example, both the Elisp manual entry and the doc string
for cond are effective.

There are people on this list who are using pcase like things, and so
clearly understand their syntax and semantics.  Could these people
PLEASE document these things, and do so before the release of Emacs
25.1.  Preferably well before.

--
Alan Mackenzie (Nuremberg, Germany).

Reply | Threaded
Open this post in threaded view
|

Re: The poor state of documentation of pcase like things.

Kaushal Modi
+1

I would welcome a short tutorial on how (and why) to use pcase.

Reply | Threaded
Open this post in threaded view
|

RE: The poor state of documentation of pcase like things.

Drew Adams
In reply to this post by Alan Mackenzie
Drive-by implementation?  Too clever by half?

(We don' need no stinkin' doc.  The code is the doc.
Anyone who needs doc is a wimp.  Etc.)

Reply | Threaded
Open this post in threaded view
|

Re: The poor state of documentation of pcase like things.

Phillip Lord-3
In reply to this post by Alan Mackenzie
Alan Mackenzie <[hidden email]> writes:
> Some of these doc strings are patronising indeed.  They all seem to say,
> implicitly, "the author's time is far too valuable to waste in writing
> meaningful documentation".

I think it's probably better to make your points (which are reasonable)
without making such aspersions. The author in question has been
extremely generous with their time.


>
> Particularly egregious is the doc string for pcase-exhaustive: "The
> exhaustive version of `pcase' (which see).".  Uhh????  Needless to say,
> the doc string of pcase makes no mention of "exhaustive".
>
> Let us analyse the documentation of the one macro which is documented to
> any meaningful extent, pcase itself:
>
> The article in the Elisp manual for pcase starts well, documenting the
> basic form and outlining the basic semantics, but then starts rambling
> on like a tutorial, rather than filling in the semantic details.  Here
> is a partial list of what is missing from that manual page:
>
> (i) A @dfn{U-PATTERN}.
> (ii) A @dfn{Q-PATTERN}.
> These two things are described only in terms of their structure, not
> what they are conceptually.  What do "U" and "Q" stand for?  What is the
> semantic significance of a Q-PATTERN?


These defined in terms, but unfortunately, the definition is a bit
recursive -- so a Q-PATTERN is defined in terms of other Q-PATTERNs (or
an atom).


> It would appear that Lisp programmers are expected to absorb the
> semantics (and sometimes even the syntax) of pcase-* by osmosis:
> studying and imitating examples.  This is a Bad Thing.


I am not 100% convinced that this is a bad thing. The actual semantics
of pcase do mess your head up a bit. The first part, the tutorial
section, is for me one of the clearest sections. I think it's something
that we should have more off, personally.

> Most (?all) of the rest of Emacs Lisp is effectively and rigorously
> documented.  For example, both the Elisp manual entry and the doc string
> for cond are effective.
>
> There are people on this list who are using pcase like things, and so
> clearly understand their syntax and semantics.  Could these people
> PLEASE document these things, and do so before the release of Emacs
> 25.1.  Preferably well before.

It is indeed worth doing these things.

Phil

Reply | Threaded
Open this post in threaded view
|

Re: The poor state of documentation of pcase like things.

John Wiegley
In reply to this post by Kaushal Modi
>>>>> Kaushal Modi <[hidden email]> writes:

> I would welcome a short tutorial on how (and why) to use pcase.

There are several examples shown here:

    http://www.emacswiki.org/emacs/PatternMatching

pcase makes a lot more sense if you're used to pattern matching in functional
languages, where you describe a pattern (not unlike destructuring-bind) whose
"shape" is intended to match the set of shapes you want to successful match
against.

Since pattern matching like this isn't something I had ever encountered
outside of FP, I agree that a tutorial is in order. I'm willing to volunteer
for this.

--
John Wiegley                  GPG fingerprint = 4710 CF98 AF9B 327B B80F
http://newartisans.com                          60E1 46C4 BD1A 7AC1 4BA2

Reply | Threaded
Open this post in threaded view
|

Re: The poor state of documentation of pcase like things.

Alan Mackenzie
In reply to this post by Phillip Lord-3
Hello, Phillip.

On Thu, Dec 17, 2015 at 01:59:56PM +0000, Phillip Lord wrote:
> Alan Mackenzie <[hidden email]> writes:
> > Some of these doc strings are patronising indeed.  They all seem to say,
> > implicitly, "the author's time is far too valuable to waste in writing
> > meaningful documentation".

> I think it's probably better to make your points (which are reasonable)
> without making such aspersions. The author in question has been
> extremely generous with their time.

I'm aware of this, and I'm not making any such asperesions.  I'm merely
trying to point out how these doc strings will be perceived by users,
should they still be in their current state at the 25.1 release.

[ .... ]

> Phil

--
Alan Mackenzie (Nuremberg, Germany).

Reply | Threaded
Open this post in threaded view
|

Re: The poor state of documentation of pcase like things.

Kaushal Modi
In reply to this post by John Wiegley
> There are several examples shown here:
>
>     http://www.emacswiki.org/emacs/PatternMatching
>

Thanks John. I have no experience with functional programming and so I
did not understand the "shape" explanation.
But now that I got some clue as to what to look for online, I will do
some digging. I will start with the emacswiki page you pointed.

Reply | Threaded
Open this post in threaded view
|

Re: The poor state of documentation of pcase like things.

Phillip Lord-3
In reply to this post by John Wiegley
John Wiegley <[hidden email]> writes:

>>>>>> Kaushal Modi <[hidden email]> writes:
>
>> I would welcome a short tutorial on how (and why) to use pcase.
>
> There are several examples shown here:
>
>     http://www.emacswiki.org/emacs/PatternMatching
>
> pcase makes a lot more sense if you're used to pattern matching in functional
> languages, where you describe a pattern (not unlike destructuring-bind) whose
> "shape" is intended to match the set of shapes you want to successful match
> against.
>
> Since pattern matching like this isn't something I had ever encountered
> outside of FP, I agree that a tutorial is in order. I'm willing to volunteer
> for this.

I'll have a go at the docstrings.

I only found out about pcase recently. It's a very useful tool, and it
deserves more use. Could I suggest it be promoted in the manual a
little. Currently, it's a subnode of "conditionals", but pattern match
is really a form of control flow in its own right.

Phil

Reply | Threaded
Open this post in threaded view
|

Re: The poor state of documentation of pcase like things.

Alan Mackenzie
In reply to this post by John Wiegley
Hello, John.

On Thu, Dec 17, 2015 at 08:34:27AM -0800, John Wiegley wrote:
> >>>>> Kaushal Modi <[hidden email]> writes:

> > I would welcome a short tutorial on how (and why) to use pcase.

> There are several examples shown here:

>     http://www.emacswiki.org/emacs/PatternMatching

> pcase makes a lot more sense if you're used to pattern matching in functional
> languages, where you describe a pattern (not unlike destructuring-bind) whose
> "shape" is intended to match the set of shapes you want to successful match
> against.

> Since pattern matching like this isn't something I had ever encountered
> outside of FP, I agree that a tutorial is in order. I'm willing to volunteer
> for this.

An external tutorial is all well and good, and very useful.  But it is
drifting off topic ever so slightly.

That topic is the state of the the documentation about pcase etc.,
_inside_ Emacs, in its doc strings and the Elisp manual.  Can we take it
that that documentation will be fixed before the release of 25.1?

> --
> John Wiegley                  GPG fingerprint = 4710 CF98 AF9B 327B B80F
> http://newartisans.com                          60E1 46C4 BD1A 7AC1 4BA2

--
Alan Mackenzie (Nuremberg, Germany).

Reply | Threaded
Open this post in threaded view
|

RE: The poor state of documentation of pcase like things.

Drew Adams
In reply to this post by Phillip Lord-3
> pattern match is really a form of control flow in its own right.

OT, but no, pattern matching per se has nothing to do with control flow.

You can *combine* pattern matching with control flow (as `pcase' does,
testing the results of pattern-match binding to control the flow).  But
pattern matching itself does not imply any effect on control flow.

Reply | Threaded
Open this post in threaded view
|

Re: The poor state of documentation of pcase like things.

Phillip Lord-3
Drew Adams <[hidden email]> writes:

>> pattern match is really a form of control flow in its own right.
>
> OT, but no, pattern matching per se has nothing to do with control flow.
>
> You can *combine* pattern matching with control flow (as `pcase' does,
> testing the results of pattern-match binding to control the flow).  But
> pattern matching itself does not imply any effect on control flow.

You are right. Currently, only pcase is documented though, hence my
(badly worded) statement.

Possibly the solution is to introduce a generic "pattern matching" node,
and then have much shorter descriptions for pcase in control flow, and
the other functions elsewhere.

Phil

Reply | Threaded
Open this post in threaded view
|

Re: The poor state of documentation of pcase like things.

John Wiegley
In reply to this post by Alan Mackenzie
>>>>> Alan Mackenzie <[hidden email]> writes:

> An external tutorial is all well and good, and very useful. But it is
> drifting off topic ever so slightly.

I was hoping the tutorial would become part of the Elisp manual.

And I agree that we should lift "Pattern Matching" to a higher-level topic.

--
John Wiegley                  GPG fingerprint = 4710 CF98 AF9B 327B B80F
http://newartisans.com                          60E1 46C4 BD1A 7AC1 4BA2

Reply | Threaded
Open this post in threaded view
|

Re: The poor state of documentation of pcase like things.

John Wiegley
In reply to this post by Kaushal Modi
>>>>> Kaushal Modi <[hidden email]> writes:

> I would welcome a short tutorial on how (and why) to use pcase.

The following is a brief pcase tutorial. I welcome any edits and comments.
Also, I wonder if anyone would be willing to hammer this into a form better
suited to the Emacs Lisp manual. I'm not familiar enough with the "language"
of that document at the moment to emulate it, though I could do some reading
next week if no one else is interested in word-smithing.

John

                         Pattern Matching with pcase

All data fits into some kind of pattern. The most explicit pattern is a
description of the data itself. Let's consider the following value as a
running example:

    '(1 2 (4 . 5) "Hello")

# Exact matches

Explicitly stated, this is a list of four elements, where the first two
elements are the integers 1 and 2, the third is a cons consisting of a car of
4 and a cdr of 5, and the fourth is the string "Hello". This states an
explicit pattern that we can match against using an equality test:

    (equal value '(1 2 (4 . 5) "Hello"))

# Pattern matches

Where patterns become useful is when we want to generalize a bit. Let's say we
want to do a similar equality test, but we don't care what the final string's
contents are, only that it's a string. Even though it's simply state, this
becomes quite difficult using an equality test:

    (and (equal (subseq value 0 3) '(1 2 (4 .5)))
         (stringp (nth 3 value)))

What we would prefer is a more direct language for encoding our description of
the *family of values we'd like to match against*. The way we said in English
was: the first three elements exactly so, and the last element, any string.
This is how we'd phrase that using `pcase':

    (pcase value
      (`(1 2 (4 . 5) ,(pred stringp))
        (message "It matched!")))

Think of `pcase' as a form of `cond', where instead of evaluating each test
for non-nil, it compares a series of *patterns* against the value under
consideration (often called the "scrutinee" in the literature). There can be
many patterns, and the first one wins, as with cond.

# Capturing matches

But `pcase' can go one step further: Not only can we compare a candidate value
against a family of possible values described by their pattern, we can also
"capture" sub-values from that pattern for later use. Continuing from the last
example, let's say we want to print the string that match, even though we
didn't care about the contents of the string for the sake of the match:

    (pcase value
      (`(1 2 (4 . 5) ,(and (pred stringp) foo))
        (message "It matched, and the string was %s" foo)))

Whenever a naked symbol like `foo' occurs as a UPattern (see next section),
the part of the value being matched at that position is bound to a local
variable of the same name.

# QPatterns and UPatterns

To master `pcase', there are two types of patterns you must know: UPatterns
and QPatterns. UPatterns are the "logical" aspect of pattern matching, where
we describe the kind of data we'd like to match against, and other special
actions to take when it matches; and QPatterns are the "literal" aspect,
stating the exact form of a particular match.

QPatterns are by far the easiest to think about. To match against any atom,
string, or list of the same, the corresponding QPattern is that exact value.
So the QPattern "foo" matches the string "foo", 1 matches the atom 1, etc.

`pcase' matches against a list of UPatterns, so to use a QPattern, we must
backquote it:

    (pcase value
      (`1 (message "Matched a 1"))
      (`2 (message "Matched a 2"))
      (`"Hello" (message "Matched the string Hello")))

The only special QPattern is the anti-quoting pattern, `,foo`, which allows
you to use UPatterns within QPatterns! The analogy to macro expansion is
direct, so you can think of them similarly.  For example:

    (pcase value
      (`(1 2 ,(or `3 `4))
       (message "Matched either the list (1 2 3) or (1 2 4)")))

# More on UPatterns

There are many special UPatterns, and their variety makes this the hardest
aspect to master. Let's consider them one by one.

## Underscore `_'

To match against anything whatsoever, no matter its type or value, use
underscore. Thus to match against a list containing anything at all at its
head, we'd use:

    (pcase value
      (`(_ 1 2)
       (message "Matched a list of anything followed by (2 3)")))

## Self-quoting

If an atom is self-quoting, we don't need to use backquotes to match against
it. This means that the QPattern `1 is identical to the UPattern 1:

    (pcase value
      (1 (message "Matched a 1"))
      (2 (message "Matched a 2"))
      ("Hello" (message "Matched the string Hello")))

## Symbol

When performing a match, if a symbol occurs within a UPattern, it binds
whatever was found at that position to a local symbol of the same name. Some
examples will help to make this clearer:

    (pcase value
      (`(1 2 ,foo 3)
       (message "Matched 1, 2, something now bound to foo, and 3"))
      (foo
       (message "Match anything at all, and bind it to foo!"))
      (`(,the-car . ,the-cdr))
       (message "Match any cons cell, binding the car and cdr locally"))

The reason for doing this is two-fold: Either to refer to a previous match
later in the pattern (where it is compared using `eq'), or to make use of a
matched value within the related code block:

    (pcase value
      (`(1 2 ,foo ,foo 3)
       (message "Matched (1 2 %s %s 3)" foo)))

## `(or UPAT ...)` and `(and UPAT ...)

We can express boolean logic within a pattern match using the `or` and `and`
Patterns:

    (pcase value
      (`(1 2 ,(or 3 4)
         ,(and (pred stringp)
               (pred (string> "aaa"))
               (pred (lambda (x) (> (length x) 10)))))
       (message "Matched 1, 2, 3 or 4, and a long string "
                "that is lexically greater than 'aaa'")))

## `pred' predicates

Arbitrary predicates can be applied to matched elements, where the predicate
will be passed the object that matched. As in the previous example, lambdas
can be used to form arbitrarily complex predicates, with their own logic.

## guard expressions

At any point within a match, you may assert that something is true by
inserting a guard. This might consult some other variable to confirm the
validity of a pattern at a given time, or it might reference a local symbol
that was earlier bound by the match itself, as described above:

    (pcase value
      (`(1 2 ,foo ,(guard (and (not (numberp foo)) (/= foo 10)))
       (message "Matched 1, 2, anything, and then anything again, "
                "but only if the first anything wasn't the number 10"))))

Note that in this example, the guard occurs at a match position, so even
though the guard doesn't refer to what is being matched, if it passes, then
whatever occurs at that position (the fourth element of the list), would be an
unnamed successful matched. This is rather bad form, so we can be more
explicit about the logic here:

    (pcase value
      (`(1 2 ,(and foo (guard (and (not (numberp foo)) (/= foo 10)))) _)
       (message "Matched 1, 2, anything, and then anything again, "
                "but only if the first anything wasn't the number 10"))))


This means the same, but associates the guard with the value it tests, and
makes it clear that we don't care what the fourth element is, only that it
exists.

## Pattern let bindings

Within a pattern we can match sub-patterns, using a special form of let that
has a meaning specific to `pcase':

    (pcase value
      (`(1 2 ,(and foo (let 3 foo)))
       (message "A weird way of matching (1 2 3)")))

This example is a bit contrived, but it allows us to build up complex guard
patterns that might match against values captured elsewhere in the surrounding
code:

    (pcase value1
      (`(1 2 ,foo)
       (pcase value2
         (`(1 2 ,(and (let (or 3 4) foo) bar))
          (message "A nested pcase depends on the results of the first")))))

Here the third value of `value2' -- which must be a list of exactly three
elements, starting with 1 and 2 -- is being bound to the local variable `bar',
but only if foo was a 3 or 4. There are many other ways this logic could be
expressed, but this gives you a test of how flexibly you can introduce
arbitrary pattern matching of other values within any UPattern.

# `pcase-let' and `pcase-let*'

That's all there is to know about `pcase'! The other two utilities you might
like to use are `pcase-let` and `pcase-let*`, which do similar things to their
UPattern counter-part `let', but as regular Lisp forms:

    (pcase-let ((`(1 2 ,foo) value1)
                (`(3 4 ,bar) value2))
      (message "value1 is a list of (1 2 %s); value2 ends with %s"
               foo bar))

Note that `pcase-let' does not fail, and always executes the correspond forms
unless there is a type error. That is, `value1' above is not required to fit
the form of the match exactly. Rather, every binding that can paired is bound
to its corresponding element, but every binding that cannot is bound to nil:

    (pcase-let ((`(1 2 ,foo) '(10)))
      (message "foo = %s" foo))   => prints "foo = nil"

    (pcase-let ((`(1 2 ,foo) 10))
      (message "foo = %s" foo))   => Lisp error, 10 is not a list

    (pcase-let ((`(1 2 ,foo) '(3 4 10)))
      (message "foo = %s" foo))   => prints "foo = 10"

Thus, `pcase-let' could be thought of as a more expressive form of
`destructuring-bind'.

The `pcase-let*' variant, like `let*', allows you to reference bound local
symbols from prior matches.

    (pcase-let* ((`(1 2 ,foo) '(1 2 3))
                 (`(3 4 ,bar) (list 3 4 foo)))
      (message "foo = %s, bar = %s" foo bar))  => foo = 3, bar = 3

However, if you name a symbol with same name in a later UPattern, it is not
used as an `eq' test, but rather shadows that symbol:

    (pcase-let* ((`(1 2 ,foo) '(1 2 3))
                 (`(3 4 ,foo) '(3 4 5)))
      (message "1 2 %s" foo))

This prints out "1 2 5", rather current match.

signature.asc (641 bytes) Download Attachment
Reply | Threaded
Open this post in threaded view
|

Re: The poor state of documentation of pcase like things.

Richard Stallman
[[[ 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. ]]]

  > There are many special UPatterns, and their variety makes this the hardest
  > aspect to master. Let's consider them one by one.

  > ## Underscore `_'

  > To match against anything whatsoever, no matter its type or value, use
  > underscore. Thus to match against a list containing anything at all at its
  > head, we'd use:

  >     (pcase value
  >       (`(_ 1 2)
  >        (message "Matched a list of anything followed by (2 3)")))

I don't follow this part.  (_ 1 2) seems to be a QPattern.
Is that right?  So how is it that an element can be a UPattern?

It would help if some of the examples used symbols inside a QPattern,
without comma, so we can see what that does.

--
Dr Richard Stallman
President, Free Software Foundation (gnu.org, fsf.org)
Internet Hall-of-Famer (internethalloffame.org)
Skype: No way! See stallman.org/skype.html.


Reply | Threaded
Open this post in threaded view
|

Re: The poor state of documentation of pcase like things.

Eli Zaretskii
In reply to this post by Phillip Lord-3
> From: [hidden email] (Phillip Lord)
> Date: Thu, 17 Dec 2015 21:16:56 +0000
> Cc: Alan Mackenzie <[hidden email]>, Emacs developers <[hidden email]>
>
> Could I suggest [pcase] be promoted in the manual a
> little. Currently, it's a subnode of "conditionals", but pattern
> match is really a form of control flow in its own right.

If that's your itch, feel free to scratch it.

IMO, that's largely a waste of your time and energy: the manual is
rarely if ever read in its entirety, or even in large portions.  Most
of its uses is to quickly find the subject whose description you need,
hopefully by using the Info-index command ("i TOPIC RET"), and read
that and perhaps some of the cross-references there.  With this use
case, the level on which a description is found is irrelevant.

Btw, the importance is in the eyes of the beholder.  You look at that
through the glasses of someone who hacks Emacs core.  Try to take the
POV of a casual Lisper who just wants to put some advanced
customizations in her ~/.emacs, for example.  IOW, advanced features
and subjects are frequently very important to power users, but much
less so to "mere mortals".  The manual is supposed to serve both types
of audience.

Bottom line: what we do need is make the description clear and
complete.  Where it appears is orders of magnitude less important.

Reply | Threaded
Open this post in threaded view
|

Re: The poor state of documentation of pcase like things.

Eli Zaretskii
In reply to this post by Alan Mackenzie
> Date: Thu, 17 Dec 2015 21:26:33 +0000
> From: Alan Mackenzie <[hidden email]>
>
> Can we take it that that documentation will be fixed before the
> release of 25.1?

It goes without saying.  I wish more people got involved in this
activity, instead of hacking on master, though.  It would help
releasing Emacs 25.1 earlier.

TIA

Reply | Threaded
Open this post in threaded view
|

Re: The poor state of documentation of pcase like things.

Eli Zaretskii
In reply to this post by John Wiegley
> From: John Wiegley <[hidden email]>
> Date: Thu, 17 Dec 2015 16:42:13 -0800
> Cc: Alan Mackenzie <[hidden email]>, Emacs developers <[hidden email]>
>
> >>>>> Kaushal Modi <[hidden email]> writes:
>
> > I would welcome a short tutorial on how (and why) to use pcase.
>
> The following is a brief pcase tutorial. I welcome any edits and comments.

Thanks, please find below a few questions of a naïve reader.

> Also, I wonder if anyone would be willing to hammer this into a form better
> suited to the Emacs Lisp manual.

I could try, but only if I understand this enough to write about it,
and if the description you posted is complete (is it?).  It's hard to
convert tutorials into a manual section otherwise.

> # QPatterns and UPatterns
>
> To master `pcase', there are two types of patterns you must know: UPatterns
> and QPatterns. UPatterns are the "logical" aspect of pattern matching, where
> we describe the kind of data we'd like to match against, and other special
> actions to take when it matches; and QPatterns are the "literal" aspect,
> stating the exact form of a particular match.

What do "Q" and "U" stand for?  "Quoted" and "Unquoted", something
else?  When introducing terminology that is not English words, you
need to help the reader form a mental model by connecting terms to
words.

> The only special QPattern is the anti-quoting pattern, `,foo`

But the example doesn't use `,foo`, it uses just ,foo.  I guess `..`
here is some markdown-style "quoting", unrelated to the Lisp
backticks?

>     (pcase value
>       (`(1 2 ,(or `3 `4))
>        (message "Matched either the list (1 2 3) or (1 2 4)")))

Do 3 and 4 really have to be quoted here?  Why?

> When performing a match, if a symbol occurs within a UPattern, it binds
> whatever was found at that position to a local symbol of the same name.

"Local symbol" here meaning what? an un-interned symbol or a local
variable by that name?

>     (pcase value
>       (`(1 2 ,foo 3)
>        (message "Matched 1, 2, something now bound to foo, and 3"))
>       (foo
>        (message "Match anything at all, and bind it to foo!"))
>       (`(,the-car . ,the-cdr))
>        (message "Match any cons cell, binding the car and cdr locally"))

So to bind something to 'foo' you just use "foo", but to bind
something to 'the-car' and 'the-cdr' you need to use ",the-car" and
",the-cdr"?  Why the inconsistency?

> The reason for doing this is two-fold: Either to refer to a previous match
> later in the pattern (where it is compared using `eq'), or to make use of a
> matched value within the related code block:
>
>     (pcase value
>       (`(1 2 ,foo ,foo 3)
>        (message "Matched (1 2 %s %s 3)" foo)))

??? Is "foo" here bound to 2 different values?  And how come the
format has 2 %s, but only one variable, foo, to provide values?

> We can express boolean logic within a pattern match using the `or` and `and`
> Patterns:
>
>     (pcase value
>       (`(1 2 ,(or 3 4)
>          ,(and (pred stringp)
>                (pred (string> "aaa"))
>                (pred (lambda (x) (> (length x) 10)))))
>        (message "Matched 1, 2, 3 or 4, and a long string "
>                 "that is lexically greater than 'aaa'")))

Why did you use 'lambda' for the 3rd predicate, but not for the 2nd?
Is it just a way to show off use of 'lambda', or is there some
significant difference between these 2 use cases that requires a
'lambda' in the latter case?  More generally, when is 'lambda'
required in a predicate like these ones?

>     (pcase value
>       (`(1 2 ,foo ,(guard (and (not (numberp foo)) (/= foo 10)))
>        (message "Matched 1, 2, anything, and then anything again, "
>                 "but only if the first anything wasn't the number 10"))))

How is using 'guard' here different from using a predicate?

> Note that in this example, the guard occurs at a match position, so even
> though the guard doesn't refer to what is being matched, if it passes, then
> whatever occurs at that position (the fourth element of the list), would be an
> unnamed successful matched.

What is the significance of an "unnamed successful matched"?

> This is rather bad form, so we can be more
> explicit about the logic here:
>
>     (pcase value
>       (`(1 2 ,(and foo (guard (and (not (numberp foo)) (/= foo 10)))) _)
>        (message "Matched 1, 2, anything, and then anything again, "
>                 "but only if the first anything wasn't the number 10"))))
>
>
> This means the same, but associates the guard with the value it tests, and
> makes it clear that we don't care what the fourth element is, only that it
> exists.

Again, how is this different from using a 'pred'?

>
> ## Pattern let bindings
>
> Within a pattern we can match sub-patterns, using a special form of let that
> has a meaning specific to `pcase':
>
>     (pcase value
>       (`(1 2 ,(and foo (let 3 foo)))
>        (message "A weird way of matching (1 2 3)")))
>
> This example is a bit contrived, but it allows us to build up complex guard
> patterns that might match against values captured elsewhere in the surrounding
> code:
>
>     (pcase value1
>       (`(1 2 ,foo)
>        (pcase value2
>          (`(1 2 ,(and (let (or 3 4) foo) bar))
>           (message "A nested pcase depends on the results of the first")))))
>
> Here the third value of `value2' -- which must be a list of exactly three
> elements, starting with 1 and 2 -- is being bound to the local variable `bar',
> but only if foo was a 3 or 4.

Why do you need the 'let' here?  Binding bar to the 3rd element can be
expressed without a 'let', I think.  And why is 'and' needed here?

> That's all there is to know about `pcase'! The other two utilities you might
> like to use are `pcase-let` and `pcase-let*`, which do similar things to their
> UPattern counter-part `let', but as regular Lisp forms:
>
>     (pcase-let ((`(1 2 ,foo) value1)
>                 (`(3 4 ,bar) value2))
>       (message "value1 is a list of (1 2 %s); value2 ends with %s"
>                foo bar))

Isn't it true that pcase-let is just a short-hand for a pcase that
assigns values according to patterns, and has nil as the default
value?  If that's true, I think it explains better what pcase-let
does, especially when backed up by an example of a pcase and the
equivalent pcase-let.

Looking at the ELisp manual's node "Pattern matching case statement",
it sounds like everything you've described is already covered there,
so perhaps what we need is more examples?

Thanks.

Reply | Threaded
Open this post in threaded view
|

Re: The poor state of documentation of pcase like things.

Rasmus-13
In reply to this post by Eli Zaretskii

Eli Zaretskii <[hidden email]> writes:

>> Could I suggest [pcase] be promoted in the manual a
>> little. Currently, it's a subnode of "conditionals", but pattern
>> match is really a form of control flow in its own right.
>
> If that's your itch, feel free to scratch it.
>
> IMO, that's largely a waste of your time and energy: the manual is
> rarely if ever read in its entirety, or even in large portions.  Most
> of its uses is to quickly find the subject whose description you need,
> hopefully by using the Info-index command ("i TOPIC RET"), and read
> that and perhaps some of the cross-references there.  With this use
> case, the level on which a description is found is irrelevant.

But by lifting it, it would appear more prominently in the TOC.  This
might cause interest on its own (I’m thinking about the pdf/tex version
here).

Rasmus


--
I hear there's rumors on the, uh, Internets. . .


Reply | Threaded
Open this post in threaded view
|

Re: The poor state of documentation of pcase like things.

Eli Zaretskii
> From: Rasmus <[hidden email]>
> Date: Fri, 18 Dec 2015 10:12:00 +0100
>
> > IMO, that's largely a waste of your time and energy: the manual is
> > rarely if ever read in its entirety, or even in large portions.  Most
> > of its uses is to quickly find the subject whose description you need,
> > hopefully by using the Info-index command ("i TOPIC RET"), and read
> > that and perhaps some of the cross-references there.  With this use
> > case, the level on which a description is found is irrelevant.
>
> But by lifting it, it would appear more prominently in the TOC.

Only in the printed book, maybe.  The TOC of the Info manual is flat:
all the nodes appear on the same level.  Are printed or PDF manuals
being used a lot these days, in preference to the Info manual?

Besides, did you ever see anyone read the TOC of a large manual?  I
didn't.  I guess someone might do that, but I cannot imagine this
being a frequent use case.

Once again, I won't object to such a change, I just think there are
lots and lots of much more important things that can and should be
done in Emacs development, even in the documentation area.  I'd love
to see the available scarce resource we have applied in those more
important areas, if possible.

Reply | Threaded
Open this post in threaded view
|

Re: The poor state of documentation of pcase like things.

Rasmus-13
Hi,

Eli Zaretskii <[hidden email]> writes:

>> But by lifting it, it would appear more prominently in the TOC.
>
> Only in the printed book, maybe.  The TOC of the Info manual is flat:
> all the nodes appear on the same level.  Are printed or PDF manuals
> being used a lot these days, in preference to the Info manual?

I very much like the pdf manuals.  They are the prettiest.  I also use the
Info and html versions, depending on mode.

> Besides, did you ever see anyone read the TOC of a large manual?  I
> didn't.  I guess someone might do that, but I cannot imagine this
> being a frequent use case.

I do.  I cannot speak for other people.

> Once again, I won't object to such a change, I just think there are
> lots and lots of much more important things that can and should be
> done in Emacs development, even in the documentation area.  I'd love
> to see the available scarce resource we have applied in those more
> important areas, if possible.

I believe you.

Rasmus

--
Hvor meget poesi tror De kommer ud af et glas isvand?

1234 ... 19