Martin Kristiansen
Martin Kristiansen

Reputation: 10222

How to use the -spec functionality in erlang

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

Answers (2)

Tadmas
Tadmas

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

werewindle
werewindle

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

Related Questions