4

是否有任何适用于 Erlang 的 VM 允许您即时编译而不是之前编译?

有可能从 shell 编译,谢谢 Martin。

Now, from the Erlang shell (or some other module!):


1> compile:file("mymod.erl").
{ok,mymod}
2> mymod:myfun().
Hello Joe

这样做有什么好处或坏处吗?你还能热交换代码吗?它是处理代码的常规用例吗?那么编译器到底给你带来了什么好处呢?

4

3 回答 3

8

在 Erlang shell 中,您可以使用c("path/to/module.erl"). 您还可以通过compile模块访问此功能,特别是compile:file/{1,2}函数。

例如,假设我们有一个文件mymod.erl

-module(mymod).
-export([myfun/0]).

myfun() -> io:format("Hello Joe~n").

现在,从 Erlang shell(或其他模块!):

1> compile:file("mymod.erl").
{ok,mymod}
2> mymod:myfun().
Hello Joe

有关更多信息,请参阅compile模块上的 Erldocs 。

你可以在运行时使用 Erlang 编译器做很多事情。例如,您可以为模块动态生成代码(使用erl_syntax!),然后编译它,甚至无需使用compile:forms/{1,2}.

(插入关于伟大权力和重大责任的标准演讲。)


你还能热交换代码吗?

是的。

它是处理代码的常规用例吗?

不会。通常 Erlang 代码会提前编译成 BEAM 字节码。根据 Erlang 是以嵌入式还是交互模式启动的,模块要么在启动时加载,要么在引用时动态加载。如果你正在构建一个release,你基本上必须提前编译。

那么编译器到底给你带来了什么好处呢?

好吧,一方面,我们可以构建紧凑的版本,而不需要编译器等不必要的组件。当然,我们还获得了提前编译的所有传统好处,尤其是不必一直浪费时间进行编译。

综上所述,除非您完全理解其中的含义并且有充分的理由不提前编译代码,否则请遵循标准做法。

于 2013-04-12T10:22:21.360 回答
7

Erlang VM 只能运行编译后的代码!如果你想解释 Erlang 代码,那么你需要一个解释器。该模块erl_eval实现了 Erlang 解释器,是标准 Erlang/OTP 发行版的一部分。Erlang shell 使用它来解释输入的表达式。

Erlang VM 中的所有代码处理,无论是编译、加载还是更新,都是在模块级别完成的,因此不可能只编译或加载一个函数。Erlang 编译器是用 Erlang 编写的,并且始终可用,并且可以编译为可以立即加载到系统中的文件或二进制文件。正如@MartinTörnwall 指出的那样,使用从shell 编译模块c(module)本质上是动态编译。

因此,在模块级别使用时自动编译代码不会有任何问题。只是当前系统并非设计为以这种方式工作,默认情况下,当它尝试加载模块时,它只会查找预编译的目标文件,即.beam文件。

于 2013-04-12T18:48:15.440 回答
2

Erlang 有一个解释器escript。整个 Erlang 档案都可以用脚本编写。几乎所有功能都可用。

默认情况下,脚本将被解释。-mode(compile).您可以通过在脚本中包含 来强制编译它。

尽管这取决于您设计应用程序的方式,但通常的做法是使用 .erl 文件进行编译和运行,而不是使用 escript 文件。

所以现在你有很多选择。

  1. 使用c(my_module)此自动加载 .beam 文件将 .erl 文件编译为 .beam。所以现有的虚拟机可以运行它。在代码中,您可以使用编译模块功能,如文件、清除和加载来动态加载和运行它。
  2. 使用 erlc、erl -make、rebar 等(Erlang 有丰富的支持)编译并保存 .erl 文件,然后运行它。您可以构建档案、启动脚本、rel 等来管理 Erlang 软件的运行和发布。这通常是生产实践。
  3. 使用 escript 并以解释模式运行所有内容。
  4. 使用 escript 并给出 -mode(compile) 选项告诉 Erlang VM 在运行时(开始运行 escript 时)编译代码并运行编译后的代码(在内存中)

这样做有什么好处或坏处吗?

编译代码比解释代码快。我现在在 Erlang 中看不到任何其他内容,因为两者都支持几乎所有内容。Erlang 甚至支持组合(从解释代码调用编译代码)

你还能热交换代码吗?

在所有情况下都是的。您的代码也应该能够处理这个问题。

它是处理代码的常规用例吗?

生产的选项 2。1 用于学习/简单开发的选项。选项 3 和 4 需要根据具体要求(可能是一次运行)。

那么编译器到底给你带来了什么好处呢?

为了清楚起见,erlc程序提供了一种通用方式来运行 Erlang 系统中的所有编译器,而compile模块为 Erlang 编译器提供了一个接口。编译器提供中间二进制 .beam 文件,它有助于运行 Erlang 代码比解释对应的代码更快。它们还捕获语法错误(编译错误)。

于 2013-04-13T04:32:03.160 回答