我试图找出SBCL中values-list
函数的实现。
src/code/eval.lisp
的源代码看起来非常简单,但为什么它不属于无限递归呢?
(defun values-list (list)
#!+sb-doc
"Return all of the elements of LIST, in order, as values."
(values-list list))
如果我这样定义一个函数foo
,它将进入无限递归:
(defun foo (list)
(foo list))
答案 0 :(得分:0)
简而言之,因为其他东西已经教会编译器如何编译对(values-list)
的调用,所以函数体中引用的(values-list)
不会引用正在定义的函数。
函数定义存在的原因有点棘手。在直接调用函数的编译代码中,编译器可以按照其他任何代码处理编译对该函数的调用。但是,仅仅因为编译器知道如何编译直接调用(values-list)
并不意味着它是一个函数 - 它实际上可以只是一个特殊的形式或宏。这个看似递归的定义确保了一个实际的函数对象存在,所以像#'values-list
这样的事情和对repl函数的调用(如果repl设置为使用解释器)按预期工作。
在这种情况下,#'values-list
是使用虚拟操作(VOP,编译器可以直接编译到机器指令上)在SBCL的每个目标平台上实现的,正如您可以看到{ {3}}
如果您想了解更多相关信息,请查看search through the source。在那篇文章中,Paul Khoung添加了对SBCL的支持,使用intel x86-64 popcnt指令编译对新函数#'popcnt
的调用,并且作为最后一步,他定义了这样的函数
(in-package "POPCNT")
(defun popcnt (x) (popcnt x))
他注意到了
并非绝对必要,但可以帮助喜欢他们的REPL的人。该 编译器知道如何编译对popcnt的调用,所以我们可以定义 popcnt ...作为对popcnt的调用。我们的新功能现在是一流的 可以从解释代码调用并传递给的值 高阶函数,如编译器的常量折叠传递。