方案 1:
如果你的代码中有任何路径与你指定的类型不匹配,那么 dialyzer会报错。
方案 2:
如果您的代码中有任何路径与您指定的类型匹配,那么透析器将不会报告错误。
diaylyzer 在制度 2 下运行。在您的情况下,如果您致电foo(hello)
:
1> c(foobar).
{ok,foobar}
2> foobar:foo(hello).
ok
3>
...然后foo()
使用所需的参数类型 atom() 调用,并foo()
返回所需的类型之一,ok
,因此透析器不会报告错误。
请记住,Dialyzer 是乐观的。它对您的代码具有象征意义,并且因为对 [foo] 的函数调用有可能成功......,Dialyzer 将保持沉默。在这种情况下不会报告类型错误。
http://learnyousomeerlang.com/dialyzer
透析器可能比您的示例更令人困惑,例如:
-module(my).
-export([test/0, myand/2]).
%-compile(export_all).
-include_lib("eunit/include/eunit.hrl").
test() ->
myand({a,b}, [1,2]).
myand(true, true) -> true;
myand(false, _) -> false;
myand(_, false) -> false.
- 你能发现代码中的错误吗?
- 透析器会发现错误吗?花点时间尝试确定您可以推断出 myand() 参数的类型。
答案: to 的第一个参数myand()
必须是一个 boolean() ......这实际上不是真的 - 看看 myand() 的最后一个子句。第一个参数也可以是任何东西。三个函数子句告诉我们第一个参数的所有可能值是:true、false 或任何值。包含所有三种可能性的类型是 any()。然后,dialyzer 查看第二个参数,dialyzer 对第二个参数的类型得出了相同的结论。因此,dialyzer 推断出的类型为myand()
:
myand(any(), any()) -> boolean().
...这意味着在透析器看来,调用myand({a,b}, [1,2])
不是错误。啊??相反,我的羽毛朋友:
1> c(my).
{ok,my}
2> my:test().
** exception error: no function clause matching my:myand({a,b},[1,2]) (my.erl, line 9)
3>
显然,myand()
代码的意图是myand()
至少需要一个 boolean() 参数——但显然,dialyzer 会单独收集每个变量的信息:
+---------------------------------------+
| 1st arg info |
| |
| info1 true |
| info2 false |
| info3 any |
| --------- |
| any() -- inferred type |
| |
+---------------------------------------+
+---------------------------------------+
| 2nd arg info |
| |
| info1 true |
| info2 any |
| info3 false |
| ------- |
| any() -- inferred type |
| |
+---------------------------------------+
因此,test()
/myand()
代码是透析器无法在您的代码中报告实际错误的情况。
有一些方法可以帮助透析器发现错误:
1) 枚举函数子句中所有可能的参数:
myand(true, true) -> true;
myand(false, true) -> false;
myand(true, false) -> false.
“Erlang 编程”p。_
如果您使用透析器,152 警告不要使用for 参数。
2) 或者,如果要枚举的案例太多,可以使用守卫来指定参数类型:
myand(true, true) -> true;
myand(false, _Y) when is_boolean(_Y) -> false;
myand(_X, false) when is_boolean(_X) -> false.
3)当然,您可以使用类型规范:
-spec myand(boolean(), boolean()) -> boolean().