无法使用文件模块编译Erlang文件

Wan*_*jun 0 erlang file

当我想编译一个简单的file.erl文件时,我收到了错误消息.

$ erlc file.erl
/opt/erlang17.5/lib/kernel-3.2/include/file.hrl:34: type date_time() undefined
Run Code Online (Sandbox Code Playgroud)

以下是file.erl的内容

-module(file).
-include_lib("kernel/include/file.hrl").

-export([file_info/1]).

file_info(Dir) ->
    {ok, F} = file:read_file_info(Dir),
    io:format("~p~n", [F#file_info.type]).
Run Code Online (Sandbox Code Playgroud)

似乎没有人报告这类问题,我做了什么有什么不对吗?

Ste*_*ski 6

研究编译问题的根本原因是有益的.编译器发出此错误:

/opt/erlang17.5/lib/kernel-3.2/include/file.hrl:34:输入date_time()undefined

看看file.hrl我们看到的第34行:

ctime  :: file:date_time() | non_neg_integer(),
Run Code Online (Sandbox Code Playgroud)

这是记录ctime字段的类型说明符#file_info{}.它声明ctime可以保存file:date_time()类型或non_neg_integer()类型的值.

错误消息特别提到date_time()类型,因为它的范围表明它是在file模块中定义的.在这种情况下,file模块是被定义和编译的模块,它隐藏了Erlang/OTP kernel应用程序提供的标准模块.标准file模块定义其date_time()类型如下:

-type date_time() :: calendar:datetime().
Run Code Online (Sandbox Code Playgroud)

file但是,我们试图编译的模块却没有.如果我们添加此类型定义会发生什么?

-module(file).
-type date_time() :: calendar:datetime().
-include_lib("kernel/include/file.hrl").

-export([file_info/1]).

file_info(Dir) ->
    {ok, F} = file:read_file_info(Dir),
    io:format("~p~n", [F#file_info.type]).
Run Code Online (Sandbox Code Playgroud)

编译包含添加的类型定义的此版本现在可以:

$ erlc file.erl
$
Run Code Online (Sandbox Code Playgroud)

我们已经修复了编译错误,所以让我们尝试使用我们编译的模块.我们启动一个Erlang shell:

$ erl
Erlang/OTP 18 [erts-7.0] [source] [64-bit] [smp:8:8] [ds:8:8:10] [async-threads:10] [hipe] [kernel-poll:false]

{"init terminating in do_boot",{undef,[{file,path_eval,[[".","/Users/user"],".erlang"],[]},{c,f_p_e,2,[{file,"c.erl"},{line,481}]},{init,eval_script,8,[]},{init,do_boot,3,[]}]}}

Crash dump is being written to: erl_crash.dump...done
init terminating in do_boot ()
Run Code Online (Sandbox Code Playgroud)

我们可以在错误消息中看到尝试调用file:path_eval/2失败,因为它未定义.因为我们的file模块隐藏了标准模块但没有提供所有相同的功能,所以只要我们的file模块隐藏了标准模块,我们甚至无法启动Erlang shell .

显然,为模块选择不同的名称不仅仅是修复原始编译错误.