Common Lisp中是否有函数原型?

the*_*bda 6 lisp common-lisp function-prototypes

我已经在普通的lisp中编程了一段时间,在我使用lisp的经验中,我还没有看到任何与C或C++中的函数原型相似的函数/宏.

目前我必须非常小心我的函数的顺序,否则,当我尝试从另一个函数调用函数时,Lisp说函数"不存在",因为它在文件的后面定义.有办法解决这个问题吗?我可以在文件顶部声明我的所有函数原型,以及下面的完整定义吗?

Jos*_*lor 13

宣告宣告

您可以使用declaim来全局声明某个东西具有某种函数类型.例如,如果定义调用undefined baz的foo1(在SBCL中),请查看首先发生的事情:

CL-USER> (defun foo1 ()
           (baz))

; in: DEFUN FOO1
;     (BAZ)
; 
; caught STYLE-WARNING:
;   undefined function: BAZ
; 
; compilation unit finished
;   Undefined function:
;     BAZ
;   caught 1 STYLE-WARNING condition
FOO1
Run Code Online (Sandbox Code Playgroud)

现在,让我们添加一个声明,声明baz是一个没有参数的函数,并返回一些东西.如果你愿意,你显然可以添加更多的类型信息,但这至少会提供baz是一个函数的arity和知识.

CL-USER> (declaim (ftype (function () t) baz))
; No value
Run Code Online (Sandbox Code Playgroud)

现在,当您定义也调用baz的foo2时,您将不会收到警告:

CL-USER> (defun foo2 ()
           (baz))
FOO2
Run Code Online (Sandbox Code Playgroud)

Declaim是一个宏,但是如果你需要能够在运行时生成其中的一些东西,你可以使用proclaim,这是一个函数.例如,

CL-USER> (dolist (f '(square cube))
           (proclaim `(ftype (function (number) number) ,f)))
NIL
CL-USER> (defun add-square-and-cube (x y)
           (+ (square x) (cube y)))
ADD-SQUARE-AND-CUBE
Run Code Online (Sandbox Code Playgroud)

也就是说,这不是非常惯用的 Common Lisp.将您需要的代码放入文件然后编译该文件并加载它是更常见的.如果由于某种原因这是不可能的,这将有效,但是如果它们可用,则值得考虑加载代码的其他选项.

Muffling警告

值得注意的是,虽然SBCL将从proclaim中获取提示或声明并静默未定义的函数警告,但该函数实际上仍未定义.其他实现(例如,CLISP)仍将发出有关未定义函数的警告.

我并不真正推荐以下方法,因为警告是有原因的,但您可以选择在评估代码时消除警告.例如,在CLISP中,当我们使用未定义的函数进行编译时会收到警告:

CL-USER> (compile nil (lambda () (baz)))
WARNING: Function BAZ is not defined
#<COMPILED-FUNCTION NIL>
1
1
Run Code Online (Sandbox Code Playgroud)

我们可以绑定一个处理程序,它将消除评估表单时发生的任何警告,但是:

CL-USER> (handler-bind ((warning
                         (lambda (x)
                           (muffle-warning x))))
           (compile nil (lambda () (baz))))
#<COMPILED-FUNCTION NIL>
1
1
Run Code Online (Sandbox Code Playgroud)

这也有它的注意事项,因为编译对未定义函数的引用可能会出现的警告类型可能会有所不同,警告的消音可能会有所不同.