emacs-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: pcase docs


From: Michael Heerdegen
Subject: Re: pcase docs
Date: Sat, 23 Jan 2016 15:22:08 +0100
User-agent: Gnus/5.13 (Gnus v5.13) Emacs/25.0.50 (gnu/linux)

Eli Zaretskii <address@hidden> writes:

> > Surely not!  I just had the time to read the code, carefully (I had to,
> > to be able to write my el-search.el thing).  Most others don't care
> > because they just don't care, I think.
>
> But this stuff is widely used, by several different individuals.  How
> do they know what to put in the code, if they, like me, are confused
> about the purpose and the usage?

Dunno.  If it helps: I had spent really a lot of time into understanding
pcase.  More time than you can probably invest, doing all the work you
do.  And I made lots of errors over weeks after had finally internalized
everything.

> > Actually `pcase-defmacro' is easy to understand if you understood
> > `defmacro': You define a pattern by its name and by the arguments it
> > will accept.
>
> But 'pcase' patterns don't accept any arguments, they are matched
> against a value of an expression.  So how to understand "arguments" in
> this context?

pcase-defmacro can only define patterns that are used like function
calls, (pattern-name pattern-args), like

 
  (pred fun)
  (guard expr)
  (or pattern...)

In the sense of pcase-defmacro, FUN, EXPR or the PATTERNs play the role
of arguments of the pattern.

> > When the pcase "compiler" finds a pattern that is defined as a
> > macro, it substitutes the "call" with the "code" returned by
> > evaluating the macro definition with the given arguments.
>
> What do you mean by "call" here?

A usage, or appearance, of the pattern.


> And how to explain that a pattern that starts with "`(list" will
> somehow end up using the pattern defined with "(pcase-defmacro map"?

No, `map' doesn't define `, it defines a pattern named `map' (that
currently is rarely used, or nowhere).

Mmh, maybe you need just a simple example.  Let's define a pcase pattern
"greater-than" that matches any number greater than a specified one, so
that e.g.

(pcase 9
  ((greater-than 2) t))  ==> t

but

(pcase (+ 0 1)
  ((greater-than (* 2 5)) t))  ==> nil.

or

(pcase "Hallo"
  ((greater-than 2) t))  ==> nil.

You could define it like this:

(pcase-defmacro greater-than (number)
  `(and (pred numberp)
        (pred (lambda (x) (< ,number x)))))

Then any occurrence of (greater-than N) in any pcase pattern is simply
substituted with

  (and (pred numberp)
       (pred (lambda (x) (< N x))))

That's it.


Of course, the variable name "x" in the above definition could lead to
name clashes (as with "conventional" macros), so you would better use an
uninterned symbol.  But with the shortcut version of `pred', we instead
can just write

(pcase-defmacro greater-than (number)
  `(and (pred numberp) (pred (< ,number))))

and avoid that problem this way.


A different simple example: here is how you could define `guard' via
`pred':

(pcase-defmacro guard (expr)
  `(pred ,(lambda () expr)))


HTH,

Michael.



reply via email to

[Prev in Thread] Current Thread [Next in Thread]