() Stefan Monnier () 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