So I'm trying to process the following nested list...
(setq *test*
'("mt" "trello"
("b" "board"
("l" org-trello-show-board-labels)
("d" org-trello-sync-buffer-down)
("u" org-trello-sync-buffer-up)
("s" "setup"
("c" org-trello-create-board-and-install-metadata)
("I" org-trello-install-board-metadata)
("u" org-trello-update-board-metadata)))
("c" "card"
("a" org-trello-assign-me)
("A" org-trello-unassign-me)
("x" org-trello-archive-card)
("X" org-trello-archive-cards)
("c" "comment"
("c" org-trello-add-card-comment)
("C" org-trello-delete-card-comment))
("k" "kill"
("c" org-trello-kill-cards)
("e" org-trello-kill-entity)))
("d" "from trello"
("b" org-trello-sync-buffer-down)
("c" org-trello-sync-card-down))
("g" org-trello-abort-sync)
("h" "help"
("k" org-trello-help-describing-bindings)
("v" org-trello-version))
("j" "jump"
("b" org-trello-jump-to-trello-board)
("c" org-trello-jump-to-trello-card))
("s" "setup"
("I" org-trello-install-key-and-token)
("c" org-trello-check-setup))
("u" "to trello"
("b" org-trello-sync-buffer-up)
("c" org-trello-sync-card-up))))
Using this recursive function:
(defun *test/pcase-test (prefix &rest tree)
(pcase tree
(`(,(and (pred consp) items))
(pcase items
(`(,(and (pred stringp) key)
,(and (pred stringp) label)
.
,children)
(push `(,*prefix-func 'org-mode ,(concat "m" prefix key) ,label) *result*)
(apply #'*test/pcase-test (concat prefix key) children))
(`(,(and (or (pred stringp) (pred symbolp)) key)
,(and (pred symbolp) fn))
(push `(,*leader-key-func 'org-mode ,(concat prefix key) ',fn) *result*))))
(_
(error "Not a valid definition:\n%s" (pp-to-string tree)))))
NB: I usually begin this function by setting *result*
as nil, and setting *prefix-func
and *leader-key-func
to specific function symbols. I plan to use nreverse
to process it's final form.
The goal is to transform this nested list into a series of function calls, *prefix-func
for nested lists beginning with two string items (while passing the subsequent items, i.e. children
, into another recursive function call, and *leader-key-func
for two-item lists consisting of a string (or a symbol) followed by a symbol (which could probably be fboundp
, but I haven't decided on that yet).
What's mystifying me is that, when I instrument this function and step through it, it run through the (,(and (pred consp) items)
once, and then (since it runs the second nested pcase
) it will match (,(and (predp stringp) key)...
, pushing at least one item into *result*
. But when I step through the second round of execution, despite the fact that when I type e
and evaluate (consp tree)
(which returns t
), it doesn't match (,(and (pred consp) items)
the second time.
I definitely don't understand what's happening, or even if I'm doing the right thing with pcase
(I've gone through this reference, this EmacsWiki entry, and even the original Emacs reference on pattern matching case, which I admit I don't fully grok. I think I'm doing the right thing, but there's a nuance here I'm not fully getting.
I note that if I replace the (_...)
with the following code, it works, but I would like it if the function to throw an error if it comes up with a nested list it doesn't understand:
(items
(dolist (item items)
(apply #'*test/pcase-test prefix item))))
I know for a fact that the above code will break if item
isn't a list, and I would rather that the function I'm using would just signal me early, rather than break further down the line. Plus, this feels like a cop-out, because then I'd just make a pattern-case that matches anything and hack a way out of my predicament, which still means I don't understand how pcase
works.
What am I doing wrong? Anyone's insight on this would be greatly appreciated, thank you!