Functional programming 公共Lisp:编译与评估

Functional programming 公共Lisp:编译与评估,functional-programming,lisp,common-lisp,sbcl,Functional Programming,Lisp,Common Lisp,Sbcl,在带有sbcl的Emacs+Slime上,一旦我在文件中定义了一个(或多个)函数,我有两个选择: 评估:例如,使用C-M-x评估defun 编译:例如,使用C-C M-k编译文件 第二个也会生成一个.fasl文件 两者之间有什么区别? 当我编译定义/文件时,引擎盖下发生了什么? 每种方法的优点和缺点是什么?计算表达式时实际发生的情况是,它被发送到sbcl,在sbcl中,必须解析表达式的文本,然后将其编译为本机代码,这些代码将存储在公共Lisp环境中的内存中 第二个方法将执行相同的操作,但将所

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

  • 评估:例如,使用C-M-x评估defun
  • 编译:例如,使用C-C M-k编译文件
第二个也会生成一个.fasl文件

两者之间有什么区别?

当我编译定义/文件时,引擎盖下发生了什么?


每种方法的优点和缺点是什么?

计算表达式时实际发生的情况是,它被发送到sbcl,在sbcl中,必须解析表达式的文本,然后将其编译为本机代码,这些代码将存储在公共Lisp环境中的内存中

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

因此,编译的好处就是加快加载速度,节省计算机工作


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

这并不是直接回答您的问题,但这对于注释来说也太长了

大多数情况下,如果我们谈论SLIME和Emacs,您都不想使用这两种选项,您可能会使用C-C-C(或M-x SLIME编译defun)。这将弹出(如果尚未打开)编译缓冲区,显示编译错误和警告,并突出显示代码中的问题。这同样适用于Flymake cursor(一旦您导航到有问题的区域,它将在minibuffer中显示问题的具体内容)

编译文件发生在一种罕见的情况下,即当您实际拥有一个以后要使用的产品时。或者,最有可能的是,您希望其他人使用它,而不必设置它。例如,如果您有一个web服务器,并且您希望系统管理员能够根据需要(重新)启动它—管理员不需要知道您的软件如何工作,只需要知道如何启动它


评估一个defun只是-它将文本发送给SWANK,但不分析结果。当然,在你这样做之后,你的口齿不清会把一些东西打印回来,但是SLIME会站在一边。

也许一个隐喻会更容易理解

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

  • 待在工人附近,告诉翻译怎么做,看看工人是怎么做的
  • 请翻译人员将任务写在纸上,然后在每次需要执行任务时将此纸交给工人
  • 如果你只需要完成一次工作,那么走哪条路没有太大区别。但是,如果你想让同一件事做很多次,而且可能是由不同的工人(全是法国人)来做,你可能需要得到带有翻译说明的论文

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

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

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


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

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

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

    CL还定义了程序生命周期的3个不同时间:编译时间、加载时间和执行时间。而且,当使用一个最(如果不是最)神秘的CL特殊运算符
    eval when
    []时,可以控制发生的情况