[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: pcase generates an unprintable expansion for a form in test erc--res
From: |
Stefan Monnier |
Subject: |
Re: pcase generates an unprintable expansion for a form in test erc--restore-initialize-priors |
Date: |
Thu, 30 May 2024 19:43:01 -0400 |
User-agent: |
Gnus/5.13 (Gnus v5.13) |
> I must admit however - I still wonder: Code and matched structures will
> be proper short-length lists most of the time - would it be possible and
> make sense to handle all list elements at the same recursion level
> instead of doing O(length) recursive descents?
I think if you look at the bytecode you'll see it uses a lot less
stack space, so the problem is not as serious as it seems.
Apart from that, for the specific case of matching against just one
pattern, we could do better. As mentioned earlier, that's what
`match*` does.
In contrast `pcase.el` is designed to solve the more general case of
pattern matching against several patterns at the same time with the goal
of avoiding repeating the same operation across the various patterns.
See below the code that `match*` generates. As you can see, it's much
less nested (but it does a lot of redundant computations even for this
one pattern).
[ Note also that the code generated by `pcase.el` (without my patch),
while much more deeply nested, is only about twice the size of the
code generated by `match*`. With my patch, it is almost the same size
(about 10% larger still). I measured the size via `prin1-to-string`
and get about the same relative results when looking at interpreted
code and the byte-compiled code.
So, I'm quite happy with `pcase.el` performance for this case. ]
Stefan
ELISP> (macroexpand '(cond* ((match* `(let* ((,p (or erc--server-reconnecting
erc--target-priors))
(,q (and ,p (alist-get 'erc-my-mode ,p))))
(unless (local-variable-if-set-p 'erc-my-mode)
(error "Not a local minor mode var: %s" 'erc-my-mode))
(setq foo (if ,q (alist-get 'foo ,p) (ignore 1 2 3))
bar (if ,q (alist-get 'bar ,p) #'spam)
baz (if ,q (alist-get 'baz ,p) nil))) EXP) RES)))
(let ((d2 EXP))
(if
(and (consp d2) (eq 'let* (nth 0 d2)) (consp (nthcdr 1 d2))
(and (consp (nth 1 d2))
(and (consp (nth 0 (nth 1 d2)))
(equal
'((or erc--server-reconnecting erc--target-priors))
(cdr (nth 0 (nth 1 d2)))))
(consp (nthcdr 1 (nth 1 d2)))
(and (consp (nth 1 (nth 1 d2)))
(consp (nthcdr 1 (nth 1 (nth 1 d2))))
(and (consp (nth 1 (nth 1 (nth 1 d2))))
(eq 'and (nth 0 (nth 1 (nth 1 (nth 1 d2)))))
(consp (nthcdr 1 (nth 1 (nth 1 (nth 1 d2)))))
(equal (car (nth 0 (nth 1 d2)))
(nth 1 (nth 1 (nth 1 (nth 1 d2)))))
(consp (nthcdr 2 (nth 1 (nth 1 (nth 1 d2)))))
(and (consp (nth 2 (nth 1 (nth 1 (nth 1 d2)))))
(eq 'alist-get
(nth 0
(nth 2 (nth 1 (nth 1 (nth 1 d2))))))
(consp
(nthcdr 1
(nth 2 (nth 1 (nth 1 (nth 1 d2))))))
(equal ''erc-my-mode
(nth 1
(nth 2
(nth 1 (nth 1 (nth 1 d2))))))
(consp
(nthcdr 2
(nth 2 (nth 1 (nth 1 (nth 1 d2))))))
(equal (car (nth 0 (nth 1 d2)))
(nth 2
(nth 2
(nth 1 (nth 1 (nth 1 d2))))))
(null
(nthcdr 3
(nth 2 (nth 1 (nth 1 (nth 1 d2)))))))
(null (nthcdr 3 (nth 1 (nth 1 (nth 1 d2))))))
(null (nthcdr 2 (nth 1 (nth 1 d2)))))
(null (nthcdr 2 (nth 1 d2))))
(consp (nthcdr 2 d2))
(equal
'(unless (local-variable-if-set-p 'erc-my-mode)
(error "Not a local minor mode var: %s" 'erc-my-mode))
(nth 2 d2))
(consp (nthcdr 3 d2))
(and (consp (nth 3 d2)) (eq 'setq (nth 0 (nth 3 d2)))
(consp (nthcdr 1 (nth 3 d2))) (eq 'foo (nth 1 (nth 3 d2)))
(consp (nthcdr 2 (nth 3 d2)))
(and (consp (nth 2 (nth 3 d2)))
(eq 'if (car (nth 2 (nth 3 d2))))
(and (consp (cdr (nth 2 (nth 3 d2))))
(equal (nth 0 (nth 1 (nth 1 d2)))
(car (cdr (nth 2 (nth 3 d2)))))
(and (consp (cdr (cdr (nth 2 (nth 3 d2)))))
(and
(consp
(car (cdr (cdr (nth 2 (nth 3 d2))))))
(eq 'alist-get
(nth 0
(car
(cdr (cdr (nth 2 (nth 3 d2)))))))
(consp
(nthcdr 1
(car
(cdr (cdr (nth 2 (nth 3 d2)))))))
(equal ''foo
(nth 1
(car
(cdr (cdr (nth 2 (nth 3 d2)))))))
(consp
(nthcdr 2
(car
(cdr (cdr (nth 2 (nth 3 d2)))))))
(equal (car (nth 0 (nth 1 d2)))
(nth 2
(car
(cdr (cdr (nth 2 (nth 3 d2)))))))
(null
(nthcdr 3
(car
(cdr (cdr (nth 2 (nth 3 d2))))))))
(equal '((ignore 1 2 3))
(cdr (cdr (cdr (nth 2 (nth 3 d2)))))))))
(consp (nthcdr 3 (nth 3 d2))) (eq 'bar (nth 3 (nth 3 d2)))
(consp (nthcdr 4 (nth 3 d2)))
(and (consp (nth 4 (nth 3 d2)))
(eq 'if (car (nth 4 (nth 3 d2))))
(and (consp (cdr (nth 4 (nth 3 d2))))
(equal (nth 0 (nth 1 (nth 1 d2)))
(car (cdr (nth 4 (nth 3 d2)))))
(and (consp (cdr (cdr (nth 4 (nth 3 d2)))))
(and
(consp
(car (cdr (cdr (nth 4 (nth 3 d2))))))
(eq 'alist-get
(nth 0
(car
(cdr (cdr (nth 4 (nth 3 d2)))))))
(consp
(nthcdr 1
(car
(cdr (cdr (nth 4 (nth 3 d2)))))))
(equal ''bar
(nth 1
(car
(cdr (cdr (nth 4 (nth 3 d2)))))))
(consp
(nthcdr 2
(car
(cdr (cdr (nth 4 (nth 3 d2)))))))
(equal (car (nth 0 (nth 1 d2)))
(nth 2
(car
(cdr (cdr (nth 4 (nth 3 d2)))))))
(null
(nthcdr 3
(car
(cdr (cdr (nth 4 (nth 3 d2))))))))
(equal '(#'spam)
(cdr (cdr (cdr (nth 4 (nth 3 d2)))))))))
(consp (nthcdr 5 (nth 3 d2))) (eq 'baz (nth 5 (nth 3 d2)))
(consp (nthcdr 6 (nth 3 d2)))
(and (consp (nth 6 (nth 3 d2)))
(eq 'if (car (nth 6 (nth 3 d2))))
(and (consp (cdr (nth 6 (nth 3 d2))))
(equal (nth 0 (nth 1 (nth 1 d2)))
(car (cdr (nth 6 (nth 3 d2)))))
(and (consp (cdr (cdr (nth 6 (nth 3 d2)))))
(and
(consp
(car (cdr (cdr (nth 6 (nth 3 d2))))))
(eq 'alist-get
(nth 0
(car
(cdr (cdr (nth 6 (nth 3 d2)))))))
(consp
(nthcdr 1
(car
(cdr (cdr (nth 6 (nth 3 d2)))))))
(equal ''baz
(nth 1
(car
(cdr (cdr (nth 6 (nth 3 d2)))))))
(consp
(nthcdr 2
(car
(cdr (cdr (nth 6 (nth 3 d2)))))))
(equal (car (nth 0 (nth 1 d2)))
(nth 2
(car
(cdr (cdr (nth 6 (nth 3 d2)))))))
(null
(nthcdr 3
(car
(cdr (cdr (nth 6 (nth 3 d2))))))))
(equal '(nil)
(cdr (cdr (cdr (nth 6 (nth 3 d2)))))))))
(null (nthcdr 7 (nth 3 d2))))
(null (nthcdr 4 d2)))
(let*
((q (nth 0 (nth 1 (nth 1 d2)))) (p (car (nth 0 (nth 1 d2)))))
RES)
nil))
ELISP>
- pcase generates an unprintable expansion for a form in test erc--restore-initialize-priors, Alan Mackenzie, 2024/05/26
- Re: pcase generates an unprintable expansion for a form in test erc--restore-initialize-priors, Michael Heerdegen, 2024/05/26
- Re: pcase generates an unprintable expansion for a form in test erc--restore-initialize-priors, Stefan Monnier, 2024/05/27
- Re: pcase generates an unprintable expansion for a form in test erc--restore-initialize-priors, Stefan Monnier, 2024/05/27
- Re: pcase generates an unprintable expansion for a form in test erc--restore-initialize-priors, Michael Heerdegen, 2024/05/27
- Re: pcase generates an unprintable expansion for a form in test erc--restore-initialize-priors, Stefan Monnier, 2024/05/27
- Re: pcase generates an unprintable expansion for a form in test erc--restore-initialize-priors, Michael Heerdegen, 2024/05/29
- Re: pcase generates an unprintable expansion for a form in test erc--restore-initialize-priors,
Stefan Monnier <=
- Re: pcase generates an unprintable expansion for a form in test erc--restore-initialize-priors, Andrea Corallo, 2024/05/31
- Re: pcase generates an unprintable expansion for a form in test erc--restore-initialize-priors, Stefan Monnier, 2024/05/31
Re: pcase generates an unprintable expansion for a form in test erc--restore-initialize-priors, F . Jason Park, 2024/05/27
Re: pcase generates an unprintable expansion for a form in test erc--restore-initialize-priors, Stefan Monnier, 2024/05/30