emacs-devel
[Top][All Lists]
Advanced

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

Re: EXPVAL in pcase-defmacro docstrings


From: Thien-Thi Nguyen
Subject: Re: EXPVAL in pcase-defmacro docstrings
Date: Thu, 31 May 2018 16:56:38 +0200
User-agent: Gnus/5.13 (Gnus v5.13) Emacs/27.0.50 (gnu/linux)

() Stefan Monnier <address@hidden>
() Wed, 30 May 2018 08:28:29 -0400

   I think this change is misguided:

   - When reading source code, you get things like:

         (pcase-defmacro radix-tree-leaf (vpat)
           "Build a `pcase' pattern that matches radix-tree leaf EXPVAL.
         VPAT is a `pcase' pattern to extract the value."

     where the EXPVAL comes out of nowhere

   - The wording "matches radix-tree leaf EXPVAL" makes it sound
     like the reader is already familiar with EXPVAL and that we
     know already that it's a radix-tree leaf, whereas the
     pattern will have to check if EXPVAL is such a leaf.

Yes.  That is awkward, when reading the source code.  Thanks for
pointing it out; i was focusing on the aggregated docstring for
that change.  For docstrings where it makes sense to use EXPVAL
(maybe not this one), how about we add a small comment pointing
to the EXPVAL convention?  That way, we retain consistency in
the presentation (for ‘C-h f pcase RET’), and give a clue to
people who read source code.

I say "maybe" because, in trying to better understand the
operation of ‘radix-tree-leaf’, i found this comment puzzling:

    ;; FIXME: We'd like to use a negative pattern (not consp),
    ;; but pcase doesn't support it.  Using `atom' works but
    ;; generates sub-optimal code.
    `(or `(t . ,,vpat) (and (pred atom) ,vpat))))

Does that mean we'd want a hypothetical ‘(pred (not consp))’ if
such a construct were supported by ‘pcase’?

Another question i have concerns ‘(t . ...)’.  My understanding
is that in a structural pattern (that begins with backquote), a
symbol represents itself.  However, IIUC the car of the nodes is
always a string.  So this subpattern never matches.

Experimenting in *scratch*, i see:

 (let ((tr radix-tree-empty)
       sub)
   (setq tr (radix-tree-insert tr "all" 0)
         tr (radix-tree-insert tr "abc" 99)
         tr (radix-tree-insert tr "abx" 2)
         sub (radix-tree-subtree tr "a"))
   (list :sub sub
         :etc (pcase sub
                ((radix-tree-leaf v) v))))
 =>
 (:sub
  (("ll" . 0)
   ("b"
    ("c" . 99)
    ("x" . 2)))
  :etc nil)
 
However, if i define ‘radix-tree-leaf-NEW’ as follows:

 (eval-and-compile
   (pcase-defmacro radix-tree-leaf-NEW (vpat)
     `(or `(,_ . ,,vpat)
          (and (pred atom)
               ,vpat))))

replacing ‘t’ w/ ‘,_’ (comma underscore) to "match anything", i
see instead:

 (let ((tr radix-tree-empty)
       sub)
   (setq tr (radix-tree-insert tr "all" 0)
         tr (radix-tree-insert tr "abc" 99)
         tr (radix-tree-insert tr "abx" 2)
         sub (radix-tree-subtree tr "a"))
   (list :sub sub
         :etc (pcase sub
                ((radix-tree-leaf-NEW v) v))))
 =>
 (:sub
  (("ll" . 0)
   ("b"
    ("c" . 99)
    ("x" . 2)))
  :etc
  (("b"
    ("c" . 99)
    ("x" . 2))))

Thinking about this a bit more, i suppose the comment makes
sense if the intention of using ‘t’ is to never match.  Since
‘pcase’ supports lambda expressions for the ‘pred’ pattern,
we can use one directly:

 (pred (lambda (x) (not (consp x))))

and then simplify the definition to something like:

 (eval-and-compile
   (pcase-defmacro radix-tree-leaf-NEW-2 (vpat)
     `(and (pred (lambda (x)
                   (not (consp x))))
           ,vpat)))

Another idea is to make ‘pcase’ support a new core pattern, say
"npred", which would be similar to ‘pred’ but invert the result
of the predicate it uses.  Here, it would be: ‘(npred consp)’.

If this interpretation is correct, i would also suggest another
change: from VPAT to VAR.  This would emphasize that VAR is the
usual vehicle for binding the leaf node "data" for use in the
clause's body forms.  (Maybe "usual" is stretching it -- i found
only one use of ‘radix-tree-leaf’ in the Emacs 26 repo.)  Using
VAR would be easier to document, too.

Anyway, the documentation can say "VAR can also be a pcase
pattern", so as not preclude more complex usage.  WDYT?

I'll respond to the remaining points in the next mail.

-- 
Thien-Thi Nguyen -----------------------------------------------
 (defun responsep (query)               ; (2018) Software Libero
   (pcase (context query)               ;       = Dissenso Etico
     (`(technical ,ml) (correctp ml))
     ...))                              748E A0E8 1CB8 A748 9BFA
--------------------------------------- 6CE4 6703 2224 4C80 7502

Attachment: signature.asc
Description: PGP signature


reply via email to

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