perf(lib): factor seq out of fn! & bake in lookup table

A little more time and space gained by cutting out seq entirely and
pre-generating the argument lookup table. At least, in uncompiled use
cases.

The original implementation used regexp to lookup arguments, which
was (relatively) expensive. By comparison, using `assq` is *much*
faster, especially for datasets this small; and more so when I get
around to byte-compiling Doom's core (assq has its own byte-compiler
opcode).
This commit is contained in:
Henrik Lissner 2022-06-21 23:19:09 +02:00
parent 1583db5983
commit 66d06261aa
No known key found for this signature in database
GPG key ID: B60957CA074D39A3

View file

@ -327,13 +327,15 @@ ARGLIST."
(allow-other-keys arglist))
,@body)))
(put 'doom--fn-crawl 'lookup-table
'((_ . 0) (_ . 1) (%2 . 2) (%3 . 3) (%4 . 4)
(%5 . 5) (%6 . 6) (%7 . 7) (%8 . 8) (%9 . 9)))
(defun doom--fn-crawl (data args)
(cond ((symbolp data)
(when-let*
((lookup '(_ _ %2 %3 %4 %5 %6 %7 %8 %9))
(pos (cond ((eq data '%*) 0)
((memq data '(% %1)) 1)
((cdr (assq data (seq-map-indexed #'cons lookup)))))))
(when-let
(pos (cond ((eq data '%*) 0)
((memq data '(% %1)) 1)
((cdr (assq data (get 'doom--fn-crawl 'lookup-table))))))
(when (and (= pos 1)
(aref args 1)
(not (eq data (aref args 1))))
@ -342,8 +344,11 @@ ARGLIST."
((and (not (eq (car-safe data) '!))
(or (listp data)
(vectorp data)))
(seq-doseq (elt data)
(doom--fn-crawl elt args)))))
(let ((len (length data))
(i 0))
(while (< i len)
(doom--fn-crawl (elt data i) args)
(cl-incf i))))))
(defmacro fn! (&rest args)
"Return an lambda with implicit, positional arguments.