为什么erlang:foo()会编译?

11
为什么Erlang编译器不能在编译时检测到未定义的函数?
如果我写一个test.erl文件:
-module(test). 
-export([start/0]).

start() ->
       erlang:foo().

编译通过。

Eshell V5.6.5  (abort with ^G)
1> c(test).
{ok,test}
2> 

但会在运行时崩溃。

2> test:start().
** exception error: undefined function erlang:foo/0

为什么编译器在编译期间不对此发出错误或警告?它应该知道有导出函数,不是吗?

3个回答

17

Erlang是一种动态语言。然而,最好在编译后进行类型检查和静态分析。

工具Dialyzer用于检查此类错误条件。

编译器在编译时不知道它的原因是因为可以在运行时(以及从远程节点)搜索并动态加载函数。Dialyzer将在运行时将代码与代码路径进行检查。

从远程节点加载代码的能力意味着可以在设备上安装基本的“系统”,然后设备可以从网络引导自己。

您还应该记住Erlang的另一个特性,即可以使用构造如on the fly的东西生成函数调用。

erlang:apply(ModuleName, FunctionName, ArgList)

在这种情况下,无法确定函数是否存在于编译时。尽管模块和函数现在可能存在于编译时,但您可以热交换模块并卸载代码,因此在运行时可能不存在。

1
不仅是代码路径,还包括 Erlang 集群中的其他节点。代码不必在本地才能加载到 Erlang VM 中并执行。 - Rob Elsner
1
我之前真的没有考虑过那个。快速查看Erlang Cookbook就可以找到如何做到这一点。http://www.trapexit.org/Remote_Code_Load - Gordon Guthrie
此外,您可以在运行时替换或卸载模块,因此即使编译器现在检查通过,以后仍可能失败。 - archaelus

0

0
我认为这是一个实现问题,因为Erlang开发人员决定采用运行时链接而不是构建时链接。部分原因可能与版本控制和/或动态代码加载有关。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接