gpt4 book ai didi

lisp - Lisp 是如何动态和编译的?

转载 作者:太空宇宙 更新时间:2023-11-03 18:32:07 26 4
gpt4 key购买 nike

我不明白 Lisp 是如何编译和动态的。对于一种能够操纵和修改并生成代码的语言,难道不是需要解释吗?一种语言是否有可能在完全编译后仍然是动态的?或者我错过了什么? Lisp 做了什么使其既可以编译又可以动态?

最佳答案

Lisp 是一个广泛的语言和实现家族。

Dynamic 在 Lisp 上下文中意味着代码在运行时具有一定的灵 active 。例如,它可以更改或替换。这与动态类型不同。

Lisp 编译

通常 Lisp 实现有一个在运行时可用的编译器。当此编译器是增量时,它不需要整个程序,但可以编译单个 Lisp 形式。那么我们说编译器支持增量编译。

请注意,大多数 Lisp 编译器不是即时编译器。作为程序员,您可以调用编译器,例如在 Common Lisp 中使用函数 COMPILECOMPILE-FILE .然后 Lisp 代码被编译。

此外,大多数同时具有编译器和解释器的 Lisp 系统允许自由混合执行解释和编译代码。

在 Common Lisp 中,还可以指示编译器编译代码的动态程度。一个更高级的 Lisp 编译器,如 SBCL 的编译器(或许多其他人)然后可以生成不同的代码。

示例

(defun foo (a)
(bar a 3))

上面的函数 foo 调用了函数 bar

如果我们有一个全局函数 bar 并重新定义它,那么在 Lisp 中我们通常期望新函数 bar 将被 foo 调用>。我们不必重新编译 foo

让我们看看GNU CLISP .它为虚拟机编译成字节码。它不是 native 代码,但出于我们的目的,它更易于阅读。

CL-USER 1 > (defun foo (a)
(bar a 3))
FOO

CL-USER 2 > (compile 'foo)

FOO
NIL
NIL

[3]> (disassemble #'foo)

Disassembly of function FOO
(CONST 0) = 3
(CONST 1) = BAR
1 required argument
0 optional arguments
No rest parameter
No keyword parameters
4 byte-code instructions:
0 (LOAD&PUSH 1)
1 (CONST&PUSH 0) ; 3
2 (CALL2 1) ; BAR
4 (SKIP&RET 2)

运行时查找

因此您看到对 BAR 的调用进行了运行时查找。它查看符号 BAR,然后调用符号的函数。因此,符号表用作全局函数的注册表。

这种运行时查找与增量编译器相结合 - 在运行时可用 - 允许我们生成 Lisp 代码,编译它,将它加载到当前的 Lisp 系统中,并让它一点一点地修改 Lisp 程序。

这是通过使用间接寻址来完成的。在运行时,Lisp 系统查找名为 bar 的当前函数。但请注意,这与编译或解释无关。如果您的编译器编译 foo 并且生成的代码使用此机制,那么它是动态的。因此,在解释代码和编译代码中都​​会有查找开销。

自 70 年代以来,Lisp 社区投入了大量精力使编译器和解释器的语义尽可能相似。

像 Common Lisp 这样的语言还允许编译器使编译后的代码不那么动态。例如,不在运行时查找代码某些部分的函数。

关于lisp - Lisp 是如何动态和编译的?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12593768/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com