公共Lisp中是否有函数原型? 我在通用LISP编程了一段时间,在我使用LISP的经验中,我还没有看到任何函数/宏,它的功能类似于C或C++中的函数原型。

公共Lisp中是否有函数原型? 我在通用LISP编程了一段时间,在我使用LISP的经验中,我还没有看到任何函数/宏,它的功能类似于C或C++中的函数原型。,lisp,common-lisp,function-prototypes,Lisp,Common Lisp,Function Prototypes,目前,我必须非常小心我的函数的顺序,否则,当我试图从另一个函数调用函数时,Lisp说该函数不存在,因为它稍后在文件中定义。有没有办法绕过这个问题?我可以在文件的顶部声明我的所有函数原型,以及下面的完整定义吗 及 可以使用全局声明某个对象具有某个函数类型。例如,如果您在SBCL中定义了调用未定义baz的foo1,那么首先会发生什么: 现在,让我们添加一个声明,声明baz是一个无参数函数,并返回一些东西。如果愿意,您显然可以添加更多的类型信息,但这至少可以提供arity和baz是函数的知识 CL-U

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

及 可以使用全局声明某个对象具有某个函数类型。例如,如果您在SBCL中定义了调用未定义baz的foo1,那么首先会发生什么:

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

CL-USER> (declaim (ftype (function () t) baz))
; No value
现在,当您定义同时调用baz的foo2时,不会得到任何警告:

CL-USER> (defun foo2 ()
           (baz))
FOO2
Declaim是一个宏,但如果您需要能够在运行时生成其中一些内容,则可以使用,这是一个函数。例如:

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
也就是说,这不是一个非常地道的通用Lisp。更常见的做法是将需要的代码放入文件中,然后编译并加载该文件。如果由于某种原因无法实现,这将是可行的,但如果有其他加载代码的选项,则值得考虑

消音警告 还值得注意的是,虽然SBCL将接受宣告或声明的提示并使未定义函数警告静音,但该函数实际上仍然未定义。其他实现(如CLISP)仍将发出有关未定义函数的警告

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

CL-USER> (compile nil (lambda () (baz)))
WARNING: Function BAZ is not defined
#<COMPILED-FUNCTION NIL>
1
1
我们可以绑定一个处理程序,该处理程序将隐藏评估表单时出现的任何警告,不过:

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

这也有其自身的注意事项,因为编译对未定义函数的引用时可能得到的警告类型可能会有所不同,警告的作用也可能有所不同。

正如Rainer指出的那样,如果正向引用位于单个编译单元内,则可以忽略此问题。但是,如果正向引用跨越编译单元,这将没有帮助。通常,这是代码分层不好的标志。低级代码调用高级代码?人们会说低级代码为高级代码提供了一个钩子

也就是说,我确实看到并编写了有这个问题的代码。意大利面代码,好吃!当您开始将巨大的源文件分解为较小的文件时,可能会出现这种情况。编译单元通常是单个文件。但请看一下编译单元。我不记得asdf没有提供方便的访问

我不知道Joshua使用提供声明的解决方案是否适用于所有CL实现。我的记忆是,很多年前,当我必须解决这个问题时,我们必须实现,我们会给函数一个替代定义,然后拼凑出一种方法来抑制定义警告


毫无疑问,可以用来看看Joshua的解决方案是否适用于各种实现。

在定义其任何方法之前,您可以将其定义为通用函数。所以,如果你写

非通用foo x y z

然后,任何调用FOO的函数都将看到一个已定义的函数,尽管它没有任何方法。随后可以将函数体作为方法添加

def方法foo x y z ;; 函数体

如果使用compile file,则当函数稍后在文件中定义并在前面使用时,通常不会看到有关函数的警告。我的程序需要lisp解释器,我使用的是load NOT compile-file@ShockWave它们应该只是警告而不是错误。它们不应该阻止您实际执行任何代码。@Shockwave:我怀疑您是否使用了解释器。解释器不会抱怨未定义的函数。您可能需要更详细地描述您实际正在做的事情以及您想要实现的目标。+1用于提及cl发布!我会马上提到,我提到的解决方案不会在所有平台上都起作用;事实上,这就是为什么我开始探索其他一些带有马弗警告的选项。
CL-USER> (handler-bind ((warning
                         (lambda (x)
                           (muffle-warning x))))
           (compile nil (lambda () (baz))))
#<COMPILED-FUNCTION NIL>
1
1