我希望有人能解释为什么
compile
功能没有像我预期的那样工作。
第一个问题:
* (compile 'square (lambda (x) (* x x)))
SQUARE
NIL
NIL
但是然后:
* (square 3)
; in: SQUARE 3
; (SQUARE 3)
;
; caught STYLE-WARNING:
; undefined function: COMMON-LISP-USER::SQUARE
;
; compilation unit finished
; Undefined function:
; SQUARE
; caught 1 STYLE-WARNING condition
* (describe 'square)
COMMON-LISP-USER::SQUARE
[symbol]
SQUARE names an undefined function
Assumed type: FUNCTION
这是什么意思?
第二个问题,重新开始:
* (defun square (x) (* x x x)) ;faulty definition
SQUARE
* (compile 'square (lambda (x) (* x x))) ;attempted correction
SQUARE
NIL
NIL
* (square 3)
27
这里旧的定义仍然有效。然而,超规范关于
compile
的说法是:“如果给出非零名称,则生成的编译函数将替换名称的现有函数定义,并且名称将作为主值返回;”。
(ps:我的目标是以编程方式定义(或更新)一个函数,但要让 sbcl 静态探查器识别它——否则,它会被忽略。另一种方法是使用统计探查器,但似乎并不可行在 windows-64 中工作。)
在 SBCL 中编译已编译的函数
问题很微妙:
(compile 'square (lambda (x) (* x x)))
COMPILE
是一个函数。现在看(lambda (x) (* x x))
。评价什么?
> (compiled-function-p (lambda (x) (* x x)))
T
这是一个编译函数!
在 SBCL 中,所有函数均默认编译。
现在我们在已经编译的函数上调用
COMPILE
。
发生什么事了?
COMPILE
有人可能会争辩说它仍然应该设置该功能。最好与维护者讨论这个问题
编译未编译的函数
这有效:
CL-USER> (compile 'square '(lambda (x) (* x x)))
SQUARE
NIL
NIL
CL-USER> #'square
#<FUNCTION SQUARE>
它之所以有效,是因为
'(lambda (x) (* x x))
求值为一个列表,这是一个有效的 LAMBDA
宏形式。编译器将成功编译此源代码,然后将 SQUARE
的符号函数设置为生成的编译函数。