在 Common Lisp 中,函数和宏之间是否存在性能差异?

数码卡

考虑以下两个定义:

(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] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

Jupyter和Common Lisp

来自分类Dev

(组成)在Common Lisp中

来自分类Dev

Common Lisp中的'()vs()

来自分类Dev

#ifndef在Common Lisp中

来自分类Dev

Common Lisp中函数之间的循环依赖

来自分类Dev

计算Common Lisp宏的参数

来自分类Dev

计算Common Lisp宏的参数

来自分类Dev

计算Common Lisp宏的参数

来自分类Dev

Common Lisp中的功能范围

来自分类Dev

更改-在Common Lisp中变为+

来自分类Dev

Common Lisp中的矩阵乘法

来自分类Dev

Common Lisp中的动态绑定

来自分类Dev

更改-在Common Lisp中变为+

来自分类Dev

Common Lisp中的功能范围

来自分类Dev

Common Lisp 中的变量范围

来自分类Dev

在 common lisp 中获取“common-lisp:setf common-lisp:list* 未定义”

来自分类Dev

Common Lisp:检查词法变量是否存在?

来自分类Dev

Common Lisp:检查词法变量是否存在?

来自分类Dev

是否可以在方案中实施Common Lisp的宏系统?

来自分类Dev

如何在Common Lisp中实现短路的“和”宏?

来自分类Dev

在Common Lisp中调用函数列表

来自分类Dev

关于Common Lisp中的MERGE函数

来自分类Dev

Common Lisp:避免对函数中的符号求值

来自分类Dev

将宏从Common Lisp转换为Clojure

来自分类Dev

Paul Graham的On Lisp(以及Ansi Common Lisp)中的撰写功能

来自分类Dev

Common Lisp:函数返回函数名

来自分类Dev

Common Lisp函数未返回任何值

来自分类Dev

Common Lisp中(loop for)和(loop:for)之间的区别

来自分类Dev

Common Lisp中的struct和class之间的区别