考虑以下两个定义:
(defun fun-add (a b) (+ a b))
(defmacro macro-add (a b) `(+ ,a ,b))
在我有限的理解中,“运行”一个函数会比一个宏快,因为“运行一个宏”还涉及代码扩展。但是,我使用 SBCL 得到以下结果:
CL-USER> (time (loop for i below 1e7
do (fun-add 15 25)))
Evaluation took:
0.180 seconds of real time
0.179491 seconds of total run time (0.179491 user, 0.000000 system)
99.44% CPU
396,303,718 processor cycles
0 bytes consed
NIL
CL-USER> (time (loop for i below 1e7
do (macro-add 15 25)))
Evaluation took:
0.034 seconds of real time
0.033719 seconds of total run time (0.033719 user, 0.000000 system)
100.00% CPU
74,441,518 processor cycles
0 bytes consed
NIL
为什么会这样?
有没有办法让它扩展多次?
事实上,是的。
这是一个例子,首先是使用宏时通常预期的情况,即宏在评估前只扩展一次:
; SLIME 2.23
CL-USER> (defmacro test () (print "EXPANDING"))
TEST
CL-USER> (test)
"EXPANDING" ;; printed
"EXPANDING" ;; return value
CL-USER> (dotimes (i 10) (test))
"EXPANDING"
NIL
现在,切换到解释模式:
CL-USER> (setf sb-ext:*evaluator-mode* :interpret)
:INTERPRET
CL-USER> (dotimes (i 10) (test))
"EXPANDING"
"EXPANDING"
"EXPANDING"
"EXPANDING"
"EXPANDING"
"EXPANDING"
"EXPANDING"
"EXPANDING"
"EXPANDING"
"EXPANDING"
如果您想开发一个宏并且不想在每次更新代码时重新编译所有调用者,解释模式对于宏来说非常有用。
但是,性能会受到惩罚,因此我认为基准测试无关紧要。此外,您最初提出的问题是将苹果与橙子进行比较,因为宏的目的与函数的目的大不相同。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句