Reputation: 10222
I'm writing up a small erlang service and I would like to put constraints on my types.
I've found the -spec functionality, and it looks to me like this is a way of 'locking' the signatures of functions to specific types.
My example would be a function like:
fib(N) when N < 3 ->
1;
fib(N) ->
fib(N-1) + fib(N-2).
adding the line
-spec fib_cps(pos_integer()) -> pos_integer().
should make sure the method atleast returns the correct type, but this does not seem to be the case..
for If I change the function to :
fib(N) when N < 3 ->
ok;
fib(N) ->
not_ok.
the code still compiles, fine and even runs.
What am I misunderstanding?
Upvotes: 6
Views: 898
Reputation: 6368
As werewindle says in another answer, -spec
is only used for analysis, not as part of the signature. If you want to verify input types, you can include checks for the type in the guard. So, in your example, you can do:
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).
Or, more idiomatically, since there are only two legitimate base cases:
fib(1) -> 1;
fib(2) -> 1;
fib(N) when is_integer(N), N >= 3 ->
fib(N-1) + fib(N-2).
This would prevent you from doing something like fib(bogus)
or fib(0.5)
or even fib(-1)
. If you try, it will fail with a badmatch
at runtime.
Note: the only functions you can use in a guard are built-in functions allowed by the runtime. Most of them are in the erlang
module.
Upvotes: 1
Reputation: 3029
Compiler skips those comments. But you can use dialyzer to do static code analysis. This tool will warn you about spec violations.
Upvotes: 11