了解 SBCL Common Lisp 中的编译函数如何工作

问题描述 投票:0回答:1

我希望有人能解释为什么

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 中工作。)

common-lisp compiler-warnings sbcl
1个回答
0
投票

在 SBCL 中编译已编译的函数

问题很微妙:

(compile 'square (lambda (x) (* x x)))

COMPILE
是一个函数。现在看
(lambda (x) (* x x))
。评价什么?

> (compiled-function-p (lambda (x) (* x x)))
T

这是一个编译函数!

在 SBCL 中,所有函数均默认编译。

现在我们在已经编译的函数上调用

COMPILE

发生什么事了?

  • 我们用名称和编译函数来调用
    COMPILE
  • SBCL 不编译该函数,它已经编译了
  • SBCL 没有设置名称,因为它还没有编译已经编译的函数

有人可能会争辩说它仍然应该设置该功能。最好与维护者讨论这个问题

编译未编译的函数

这有效:

CL-USER> (compile 'square '(lambda (x) (* x x)))
SQUARE
NIL
NIL

CL-USER> #'square
#<FUNCTION SQUARE>

它之所以有效,是因为

'(lambda (x) (* x x))
求值为一个列表,这是一个有效的
LAMBDA
宏形式。编译器将成功编译此源代码,然后将
SQUARE
的符号函数设置为生成的编译函数。

© www.soinside.com 2019 - 2024. All rights reserved.