总觉得哪里不对劲
[lisp] (while key-defs
(let* ((key (pop key-defs))
(def (if (eq group nil)(pop key-defs) group)))
[/lisp]
列表里的每个值都要执行一次 if ,太没有效率(当然这是因为多了一种情况需要判定,否则的话还是可以的)。决定还是用原来的方式,不过把参数由一维列表转换成二维列表。
也没找到现成的函数,自己写一个吧
[lisp](defun 2list (lst)
(if lst
(cons
(list (car lst)(cadr lst))
(2list (cddr lst)))))
[/lisp]
把 (1 2 3 4 5 6) 转换成 ((1 2)(3 4)(5 6))
[lisp](defun define-key-s (keymap key-defs &optional group)
(let ((map (cond
((eq keymap 0) (current-global-map))
((eq keymap 1) (current-local-map))
(t keymap)))
(defs (if (null group)
(2list key-defs)
(mapcar (lambda (k) (list k group)) key-defs))))
(mapc
(lambda (d) (define-key map (eval `(kbd ,(car d))) (cadr d)))
defs)))
[/lisp]
感觉速度快了不少
不过听说递归不给力,尾递归要强大一些
[lisp](defun t2list (lst acc)
(if (caddr lst)
(t2list (cddr lst)
(cons (list (caddr lst)(cadddr lst)) acc ))
acc))
(defun tlist (lst)
(t2list lst (list (list (car lst)(cadr lst)))))
[/lisp]
样子土了些…… 标准的写法得用 labels,但是 elisp 里面没有这个东东,得 require 'cl-macs ,不费那劲了,反正效果差不多
[lisp](test-times 1000 (test-list 100 2list)) ;=> 1.35
(test-times 1000 (test-list 100 tlist)) ;=> 1.42
[/lisp]根据我测试的结果,似乎尾递归还要略慢一点……
不过尾递归在空间上的要求似乎要低一点,max-lisp-eval-depth 为 1000 的条件下
[lisp](test-list 660 2list)
(test-list 990 tlist)
[/lisp]尾递归版本能够计算的数组要多一半……总之是相当的诡异
测试用到的两个宏
[lisp](defmacro test-list (n &rest fn)
"用大小为 n 的字符串列表,测试函数 fn (fn 最后一个参数为列表)"
`(let* ((i ,n)(x nil))
(while (> i 0)
(setq x (cons (number-to-string i) x))
(setq i (- i 1)))
(,@fn x)
))
(defmacro test-times (n &rest body)
"计算 body 运行 n 次所需时间"
`(let ((tm ,n)(beg (time-to-seconds)))
(while (> tm 0)
(progn ,@body)
(setq tm (1- tm)))
(- (time-to-seconds) beg)
))
;; 例子
;(test-times 100 (test-list 9 define-key-s (current-local-map)))
[/lisp]