作为在 erlang-bugs 列表中报告错误的副作用,我从透析器和打字机的发明者 Kostis Sagonas 那里得到了详细的回答。
对于我的附带问题,我得到了以下出色而详细的答案:
On Sun, May 1, 2011 at 5:53 PM, Kostis Sagonas wrote:
Peer Stitzinger 写道:
顺便说一句:在执行 --annotate 时没有收到任何警告是否正常
在打字机中,然后在没有手动调整规范的透析器中
是的。其实typer只是dialyzer基本类型推断的一个前端(即没有warning标识组件)。
IMO,如果您不打算手动“按摩”您获得的规格并为其中一些规格提供更多信息,那么这样做几乎没有意义。看看你以前的程序。两个 :64,:_*8>> 类型指的是同一个数量这一事实,如果您引入如下所示的类型,则可以更好地表达:
-type packet() :: <<_:64,_:_*8>>,
同样适用于频道:
-type channel() :: atom() | pid() |{atom(),_}.
然后规范看起来会更好。此外,dialyzer/typer 没有关于您打算在函数 recv/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 返回其第二个参数中的乐趣返回的任何类型。你可能知道这个类型是什么,所以你也应该为它引入一个类型并使用它的正确名称。
希望这会有所帮助,
科斯蒂斯
PS。很遗憾您在 erlang-bugs 中发布了此内容,因为上面包含的信息在 IMO 中比实际的错误更有趣。
由于他引用了我的错误报告中包含的代码片段,因此我将其包含在此处。以下代码片段由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}.