In std Elixir packages there are a lot of lines like
@type t :: %__MODULE__{}
I know that the @type
annotation is used to alias short notation of type in @spec
annotations, but this line is used in modules such as uri.ex which has no @spec
annotations at all.
What is the purpose of this annotation?
__MODULE__ is a compilation environment macros which is the current module name as an atom. Now you know alias __MODULE__ just defines an alias for our Elixir module. This is very useful when used with defstruct which we will talk about next. In the following example, we pass API.
For this purpose Elixir has @spec annotation to describe the specification of a function that will be checked by compiler. However in some cases specification is going to be quite big and complicated. If you would like to reduce complexity, you want to introduce a custom type definition.
Elixir is a dynamically typed language, so all types in Elixir are checked at runtime. Nonetheless, Elixir comes with typespecs, which are a notation used for: declaring typed function signatures (also called specifications); declaring custom types.
In order to call a function in Elixir we want to use the module name, in this case 'Calculator', and then the function we want to invoke, we'll use squared here. And pass in any arguments the function expects. Great all the functions from our Calculator module returned the values we expected.
First of all, types specified with the @type
directive are public by default (as opposed to types defined with @typep
). This means that even if a module has no specs in it, defining a type allows other developers to use that type when writing their functions:
@doc "Computes the length of a URI." @spec foo(URI.t) :: non_neg_integer def foo(uri), do: # ...
__MODULE__
is a special form that expands to the current module name as an atom (see the docs for it), so this:
defmodule MyModule do @type t :: %__MODULE__{} end
will define a MyModule.t
type. The most common use of the t
type is for representing structs and protocols (e.g., Enum.t
). This pattern is extremely common:
defmodule User do defstruct [:name, :email] @type t :: %__MODULE__{name: String.t, email: String.t} end
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With