我正在写一个小的erlang服务,我想对我的类型设置约束。
我找到了-spec功能,在我看来,这是一种将函数签名“锁定”到特定类型的方法。
我的例子就是这样的函数:
fib(N) when N < 3 ->
1;
fib(N) ->
fib(N-1) + fib(N-2).
添加行
-spec fib_cps(pos_integer()) -> pos_integer().
应确保atleast方法返回正确的类型,但似乎并非如此..
如果我将功能更改为:
fib(N) when N < 3 ->
ok;
fib(N) ->
not_ok.
代码仍然编译,很好甚至运行。
我误解了什么?
答案 0 :(得分:11)
编译器会跳过这些评论。但您可以使用透析器进行静态代码分析。此工具将警告您有关规范违规的信息。
答案 1 :(得分:1)
正如werewindle中another answer所述,-spec
仅用于分析,而不是签名的一部分。如果要验证输入类型,可以包括检查防护中的类型。因此,在您的示例中,您可以执行以下操作:
fib(N) when is_integer(N), N > 0, N < 3 ->
1;
fib(N) when is_integer(N), N >= 3 ->
fib(N-1) + fib(N-2).
或者,更具惯用性,因为只有两种合法的基本情况:
fib(1) -> 1;
fib(2) -> 1;
fib(N) when is_integer(N), N >= 3 ->
fib(N-1) + fib(N-2).
这会阻止您执行fib(bogus)
或fib(0.5)
甚至fib(-1)
之类的操作。如果您尝试,它将在运行时以badmatch
失败。