 Apply v.s. Reduce

#1

`1 + 2 + 3 + ... + 10000000` 时间对比：

``````(setq numbers (number-sequence 1 (expt 10 7)))

(chart-bar-quickie
'vertical
"Apply v.s. Reduce"
'("Apply" "Loop" "seq-reduce" "cl-reduce") "Method"
(mapcar
#'car
(list (benchmark-run (apply #'+ numbers))
(benchmark-run-compiled (cl-loop for i in numbers
sum i))
(benchmark-run (seq-reduce #'+ numbers 0))
(benchmark-run (cl-reduce #'+ numbers))))
"Seconds")
``````
``````(benchmark-run (apply #'+ numbers))
;; => (0.155604 0 0.0)

(benchmark-run-compiled
(cl-loop for i in numbers
sum i))
;; => (0.316804 0 0.0)

(benchmark-run 1 (seq-reduce #'+ numbers 0))
;; => (1.328944 0 0.0)

(benchmark-run (cl-reduce #'+ numbers))
;; => (1.814373 1 0.4932320000000061)
``````

#2

#3

``````(let ((numbers (number-sequence 1 (expt 10 7))))
(chart-bar-quickie
'vertical
"Apply v.s. Reduce"
'("Apply" "Loop" "seq-reduce" "cl-reduce" "-reduce") "Method"
(mapcar
#'car
(list (benchmark-run (apply #'+ numbers))
(benchmark-run-compiled (cl-loop for i in numbers
sum i))
(benchmark-run (seq-reduce #'+ numbers 0))
(benchmark-run (cl-reduce #'+ numbers))
(benchmark-run (-reduce #'+ numbers))))
"Seconds"))
``````

#4

`apply` 调用了一次，`reduce` 调用了 `(1- (length numbers))` 次：

``````(apply '+ '(1 2 3))
;; => (+ 1 2 3)

(-reduce '+ '(1 2 3))
;; => (+ (+ 1 2) 3)
``````

reduce 在这个测试中是比较吃亏的，`+` 函数没有体现 reduce 的意义：

``````(-reduce (lambda (acc n)
(+ acc n))
'(1 2 3))
``````

#5

chart 在 elisp 手册里都没有，究竟是怎么发现这个东西的……

#6

#7 感谢分享，很赞的博客。

#8