透析器不会发出此函数返回类型不一致的信号:
-spec myfun(integer()) -> zero | one.
myfun(0) -> zero;
myfun(1) -> one;
myfun(2) -> other_number.
但它会在最后一行是
myfun(_) -> other_number.
为何会这样呢?我相信上面的例子应该是非常简单的。
谢谢
发布于 2016-04-15 22:06:42
“为什么透析器不能...”这类问题的简单答案是“因为它被设计成总是正确的”,或者“因为它从来没有承诺过它会捕捉到所有东西或任何特定的东西”。
对于更复杂的答案,您需要进一步指定您的问题。如果我把你的例子写在一个模块中:
-module(bar).
-export([myfun1/1, myfun2/1]).
-spec myfun1(integer()) -> zero | one.
myfun1(0) -> zero;
myfun1(1) -> one;
myfun1(2) -> other_number.
-spec myfun2(integer()) -> zero | one.
myfun2(0) -> zero;
myfun2(1) -> one;
myfun2(_) -> other_number.
对它进行透析:
$ dialyzer bar.erl
Checking whether the PLT /home/stavros/.dialyzer_plt is up-to-date... yes
Proceeding with analysis... done in 0m0.64s
done (passed successfully)
..。这两个差异都不是“检测到”的,因为两者都不是“错误”。只是代码在某些方面比规范更通用(可以返回额外的值),在某些方面比规范更严格(对于版本1,不能处理每个整数)。
第二个版本的问题可以在-Woverspecs
中找到
$ dialyzer -Woverspecs bar.erl
Checking whether the PLT /home/stavros/.dialyzer_plt is up-to-date... yes
Proceeding with analysis...
bar.erl:11: Type specification bar:myfun2(integer()) -> 'zero' | 'one' is a subtype of the success typing: bar:myfun2(_) -> 'one' | 'other_number' | 'zero'
done in 0m0.58s
done (warnings were emitted)
该警告确切地解释了规范比代码更严格。
这两个问题也可以通过极不寻常的-Wspecdiffs
检测到
$ dialyzer -Wspecdiffs bar.erl
Checking whether the PLT /home/stavros/.dialyzer_plt is up-to-date... yes
Proceeding with analysis...
bar.erl:5: Type specification bar:myfun1(integer()) -> 'zero' | 'one' is not equal to the success typing: bar:myfun1(0 | 1 | 2) -> 'one' | 'other_number' | 'zero'
bar.erl:11: Type specification bar:myfun2(integer()) -> 'zero' | 'one' is a subtype of the success typing: bar:myfun2(_) -> 'one' | 'other_number' | 'zero'
done in 0m0.61s
done (warnings were emitted)
既不鼓励-Woverspecs
也不鼓励-Wspecdiffs
操作模式,因为透析器的类型分析可以并将泛化类型,因此“以更具限制性的方式指定某些内容”可能是泛化的结果。
也可以是这样的,你只想用0和1作为参数来调用这些函数,在这种情况下,规范是“ok”。
https://stackoverflow.com/questions/36645013
复制相似问题