Common Lisp:编译与评估

时间:2012-08-02 17:48:55

标签: functional-programming lisp common-lisp sbcl

在使用sbcl的Emacs + Slime上,一旦我在文件中定义了一个函数(或更多),我有两个选择:

  • 评估:例如使用C-M-x eval-defun
  • 编译:例如用C-c M-k编译文件

第二个也生成一个.fasl文件。

两者之间有什么区别?

编译定义/文件时,幕后发生了什么?

每个人的优点和缺点是什么?

4 个答案:

答案 0 :(得分:7)

首先,有一个函数eval [1],它允许在语言运行时评估(即执行)任意CL表单。 CL实现可以具有2种不同的操作模式:编译模式和解释模式。编译模式意味着,在评估之前,表单首先在内存中编译。同样在CL评估中,不是在文件级别,而是在单个表单的级别上。所以eval可以编译和解释表单,具体取决于操作模式。 (例如,默认情况下,SBCL始终编译,除非您通过将sb-ext:*evaluator-mode*设置为:interpret来指示它,而CLISP始终解释)。

现在,还有一个便捷函数compile-file [2],它允许编译某个文件中的所有表单并将结果保存在另一个文件中。 不会触发这些表单的评估

CL还定义了3个不同的程序生命周期:编译时,加载时和执行时。并且有可能控制使用最多(如果不是最多)隐藏的CL特殊操作符eval-when [3]之一时发生的事情。

总而言之, C-M-x eval-defun 将在光标下的表单上调用eval。它不需要编译它,但这可能,具体取决于实现。 C-c M-k编译文件compile-file你的缓冲区,但不评估它的内容。

答案 1 :(得分:3)

也许隐喻会更容易理解。

想象一下,你有一些工作要做,而且工作人员可以做到。不幸的是,这名工人不懂你的语言。假设你说英语,他只懂法语。所以你需要翻译。好的,没问题,你也有翻译。这里有2个选项:

  1. 靠近工人,告诉翻译要做什么,看看工人是怎么做的。
  2. 要求翻译人员将任务写入论文,然后在每次需要执行作业时将此论文提交给工作人员。
  3. 如果你只需要完成一次工作,那么走哪条路就没有什么大不同了。但是,如果您希望多次完成同样的事情,并且可能由不同的工作人员(所有法国人)完成,您可能希望获得带有翻译说明的论文。

    现在编程。你用一种语言编写程序(例如Common Lisp),但计算机本身并不理解它。它“只说”其内部语言 - 本机代码。所以你需要某种翻译。这就是编译器进入游戏的地方。编译器将您的代码转换(编译)为本机代码,以便计算机可以执行它。

    就像法国工人的例子一样,你有两个选择:

    1. 告诉计算机在您需要时做什么。在这种情况下,编译器将翻译指令,计算机将执行它们,并且两者都会立即忘记它。这称为评估
    2. 将指令写入文件,然后用它告诉计算机每次需要时该怎么做。这通常称为编译
    3. 注意术语中的混乱:实际上,编译器在两种情况下都有效,但是当你比较评估和编译时,后者仅指第二种情况。在其他情况下,术语可能不同,因此在阅读评估,编译,解释和一般翻译等内容时,尝试理解基础过程。

      另请注意,在SBCL REPL编译中(写入文件)具有评估的副作用。因此在这种特定情况下,唯一的区别在于写入文件。

答案 2 :(得分:2)

评估表达式时实际发生的是它被发送到sbcl,其中表达式的文本必须被解析,然后编译成本机代码,该代码将存储在Common Lisp环境的内存中。

第二种方法也会这样做,但会将所有代码编译到文件中。您希望编译代码的原因是为了加快编写速度;没有必要解析代码的语法和语义并再次生成代码,只需将其加载到内存中就可以运行。

因此编译的好处只是加载速度,节省了计算机的工作量。

在编辑已经编译过的文件的情况下,您可以eval-defun只在内存中重新创建一个函数,这可能比编译整个文件更快。

答案 3 :(得分:1)

这不是直接回答你的问题,但这对评论来说太长了。

大多数时候你不想使用任何一个选项,如果我们谈论SLIME和Emacs - 你将使用 Cc Cc ,(或 Mx slime-compile- defun定义)。这将弹出(如果尚未打开)编译缓冲区,它显示编译错误和警告+它将突出显示代码中的问题。这也适用于Flymake光标(一旦你导航到有问题的区域,它将在迷你缓冲区中显示究竟是什么问题)。

当您实际拥有要在以后使用的产品时,编译文件的情况很少发生。或者,很可能,您希望其他人使用它而无需您进行设置。例如,如果您有一台Web服务器,并且您希望系统管理员能够根据需要(重新)启动它 - 管理员不需要知道您的软件如何运行,她只需要知道如何启动它

Eval'ing defun就是这样 - 它将文本发送到SWANK,但不分析结果。当然,你的Lisp会在你做完后给你打印一些东西,但是SLIME会站在一边。