It seems like when you define a behaviour you have to include type specs within the @callback
definition. Then when you adopt the behaviour, the compiler requires that the function_name/arity
is defined, but is perfectly happy if you don't follow the type specs.
My questions are:
- Are those observations correct?
- If yes, why does
@callback
couple type specs with the actual functionality of checking that thefunction_name/arity
is defined? It makes it difficult to understand what is documentation and what is core functionality. The rest of Elixir seems to clearly separate the two, keeping type specs as an optional addition.
For example:
If we omit the type specs, we get a compile error
defmodule Greeting do
@callback hello(person)
end
# (CompileError) iex:82: type specification missing return type: hello(person)
To make the compiler happy, we have to include type specs:
defmodule Greeting do
@callback hello(%Person{}) :: {:ok, String.t} | {:error, String.t}
end
Now when we adopt the behaviour, the compiler checks that function_name/arity
is defined:
defmodule WesternGreeting do
@behaviour Greeting
def hello(), do: "Howdy"
end
# warning: undefined behaviour function hello/1 (for behaviour Greeting)
However all the type specs in the @callback are disregarded by the compiler:
defmodule WesternGreeting2 do
@behaviour Greeting
def hello([a, b, c]), do: a <> b <> c
end
# No warnings or errors
# (CompileError) iex:82: type specification missing return type: hello(person)
That seems to suggest it's indeed checked by the compiler. Am I missing something? – Hysteric