如何在erlang中使用-spec功能

时间:2011-12-14 13:51:56

标签: types casting erlang

我正在写一个小的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.

代码仍然编译,很好甚至运行。

我误解了什么?

2 个答案:

答案 0 :(得分:11)

编译器会跳过这些评论。但您可以使用透析器进行静态代码分析。此工具将警告您有关规范违规的信息。

答案 1 :(得分:1)

正如werewindleanother 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失败。

注意:您可以在guard中使用的唯一函数是运行时允许的内置函数。其中大多数都在erlang模块中。