Erlang 使用typer注释后透析机的运行未显示任何警告
在一个有大约6000行Erlang代码但没有类型Erlang 使用typer注释后透析机的运行未显示任何警告,erlang,typechecking,dialyzer,Erlang,Typechecking,Dialyzer,在一个有大约6000行Erlang代码但没有类型-spec()注释的项目中,我尝试了以下方法: typer --annotate *.erl 我将所有*.erl文件替换为带注释的文件,然后运行 dialyzer --src -c *.erl 我本以为会收到很多警告(第一次运行了透析器/打字机组合),但完成后,透析器报告的所有内容都是用户默认的2个旧调用,同时不存在函数 没有触发其他默认警告 我使用它时犯了错误,还是这样的结果很常见 自动注释与打字机和透析器的组合是否没有那么有用,或者我只是运
-spec()
注释的项目中,我尝试了以下方法:
typer --annotate *.erl
我将所有*.erl
文件替换为带注释的文件,然后运行
dialyzer --src -c *.erl
我本以为会收到很多警告(第一次运行了透析器/打字机组合),但完成后,透析器报告的所有内容都是用户默认的2个旧调用,同时不存在函数
没有触发其他默认警告
我使用它时犯了错误,还是这样的结果很常见
自动注释与打字机
和透析器
的组合是否没有那么有用,或者我只是运气好,代码没有问题
旁注:我不得不注释掉3或4个
-spec()
s,因为透析器
我正在使用来自Erlang R13B04的透析器v2.2.0和打字机版本v0.1.7.4,作为在Erlang bugs列表中报告错误的副作用。我从透析器和打字机的发明者Kostis Sagonas那里得到了详细的答案 对于我的附带问题,我得到了以下伟大而详细的答案: 佩尔·斯特里辛格写道: 顺便说一句:仅仅做--annotate时不收到任何警告是正常的吗 在打字机和透析器中,无需手动调整规格 对。事实上,打字机只是透析器基本类型推断的前端(即没有警告标识组件) 依我看,如果你不打算手动“按摩”你得到的规格,并为其中一些规格提供更多信息,那么这样做就没有什么意义。看看你以前的计划。如果您引入的类型如中所示,则可以更好地表示这两种类型指的是相同数量的事实:
-type packet() :: <<_:64,_:_*8>>,
然后规格就已经看起来更好了。另外,透析器/打字机没有关于您打算在functionrecv/3
的第二个参数中使用哪种类型的乐趣的信息,但是您有!从代码中可以清楚地看出,它需要#can_pkt{}
记录,所以为什么不向其字段添加适当的类型并为其引入一个类型呢
-record(can_pkt, {id :: id(), data :: binary(), timestamp :: ts()}).
-type can_pkt() :: #can_pkt{}.
然后,规格可以看起来更好:
-spec recv(packet(), fun((can_pkt()) -> R), channel()) -> R.
-spec decode(packet()) -> can_pkt().
请注意,我使用了占位符类型变量R
来表示函数recv/2
返回第二个参数中的fun返回的任何类型。您可能知道这个类型是什么,所以还应该为它引入一个类型并使用它的专有名称
希望这有帮助
科斯蒂斯
另外,很遗憾你在erlang bug中发布了这篇文章,因为上面包含的信息比实际的bug更有趣
因为他引用了一个代码片段,所以我把它包括在我的bug报告中,我把它包括在这里。以下代码片段由typer--annotate
自动注释:
-record(can_pkt, {id, data, timestamp}).
-spec recv(<<_:64,_:_*8>>,fun((_) ->
any()),atom() | pid() | {atom(),_}) -> any().
recv(Packet, Recv_fun, Chan) ->
P = decode(Packet),
#can_pkt{id=Can_id, data=Can_data}=P,
Recv_fun(P).
-spec decode(<<_:64,_:_*8>>) ->
#can_pkt{id::<<_:11>>,data::binary(),timestamp::char()}.
decode(<<_:12, Len:4, Timestamp:16,
0:3, Id:11/bitstring, 0:18,
Data:Len/binary, _/binary>>) ->
#can_pkt{id=Id, data=Data, timestamp=Timestamp}.
-记录(can_pkt,{id,data,timestamp})。
-规格录制(,乐趣)->
any()),atom()| pid()|{atom(),})->any()。
recv(小包,recv_fun,Chan)->
P=解码(数据包),
#can_pkt{id=can_id,data=can_data}=P,
记录乐趣(P)。
-规范解码()->
#can_pkt{id::,data::binary(),timestamp::char()}。
解码()->
#can_pkt{id=id,data=data,timestamp=timestamp}。
-record(can_pkt, {id, data, timestamp}).
-spec recv(<<_:64,_:_*8>>,fun((_) ->
any()),atom() | pid() | {atom(),_}) -> any().
recv(Packet, Recv_fun, Chan) ->
P = decode(Packet),
#can_pkt{id=Can_id, data=Can_data}=P,
Recv_fun(P).
-spec decode(<<_:64,_:_*8>>) ->
#can_pkt{id::<<_:11>>,data::binary(),timestamp::char()}.
decode(<<_:12, Len:4, Timestamp:16,
0:3, Id:11/bitstring, 0:18,
Data:Len/binary, _/binary>>) ->
#can_pkt{id=Id, data=Data, timestamp=Timestamp}.