6

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

  • 评估:例如使用 CMx eval-defun
  • 编译:例如使用 Cc Mk 编译文件

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

两者有什么区别?

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

各有什么优缺点?

4

4 回答 4

8

首先,有一个函数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-filecompile-file您的缓冲区,但不评估它的内容。

于 2012-08-03T05:29:41.880 回答
4

也许一个比喻会更容易理解。

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

  1. 靠近工人,告诉翻译做什么,看看工人是怎么做的。
  2. 要求翻译人员将任务写在纸上,然后在每次需要执行工作时将此纸交给工人。

如果您只需要完成一次工作,那么走哪条路没有太大区别。但是,如果您希望同一件事多次完成,并且可能由不同的工人(全是法国人)完成,您可能希望获得带有翻译说明的论文。

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

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

  1. 告诉计算机在需要时做什么。在这种情况下,编译器将翻译指令,计算机将执行它们,两者都会立即忘记它。这称为评估
  2. 将指令写入文件,然后在每次需要时使用它来告诉计算机要做什么。这通常称为编译

请注意术语中的混乱:实际上,编译器在这两种情况下都有效,但是当您比较评估和编译时,后者仅指第二种情况。在其他情况下,术语可能会有所不同,因此在阅读评估、编译、解释和一般翻译等内容时,请尝试理解基本过程。

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

于 2012-08-03T00:25:35.920 回答
2

当你评估一个表达式时,实际发生的事情是它被发送到 sbcl,在那里你的表达式文本将被解析然后编译成本地代码,这些本地代码将存储在 Common Lisp 环境的内存中。

第二种方法将执行相同的操作,但将所有代码编译到文件中。您想要编译代码的原因是为了加快加载速度;无需解析代码的语法和语义并再次生成代码,只需将其加载到内存中即可运行。

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

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

于 2012-08-02T21:55:05.093 回答
1

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

大多数情况下,如果我们谈论 SLIME 和 Emacs,您不会喜欢使用任何一个选项 - 您会使用C-c C-c, (或M-x slime-compile-defun)。这将弹出(如果尚未打开)编译缓冲区,其中显示编译错误和警告+它将突出显示代码中的问题。这也适用于 Flymake 光标之类的东西(一旦您导航到有问题的区域,它将在 minibuffer 中显示究竟是什么问题)。

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

评估一个 defun 就是这样 - 它将文本发送到 SWANK,但不分析结果。当然,你的 Lisp 会在你这样做之后打印一些东西给你,但 SLIME 会搁置一旁。

于 2012-08-02T23:24:16.720 回答