View Source TypeCheck.External (TypeCheck v0.13.7)
Working with regular Elixir and Erlang @spec
and @type
definitions.
Experimental
This module is experimental. The API of the various functions in this module are not yet stable; they might change slightly in future minor versions of the library.
If you encounter a problem, please, open an issue.
Summary
Functions
Non-raising version of TypeCheck.External.apply!/4
.
Ensures values conform to the given type.
The same as Kernel.apply/3
but ensures that values conform the given type.
Ensure at runtime that arguments at result of function call conform the function spec.
Extract TypeCheck type from the regular Elixir (or Erlang) @spec
of the given function.
Extract TypeCheck type from the regular Elixir (or Erlang) @type
with the given name.
Functions
@spec apply(TypeCheck.Type.t(), module(), atom(), list()) :: {:ok, any()} | {:error, TypeCheck.TypeError.t()}
Non-raising version of TypeCheck.External.apply!/4
.
Ensures values conform to the given type.
Returns {:error, reason}
on failure, {:ok, function_call_result}
otherwise.
iex> alias TypeCheck.Builtin, as: B
iex> type = B.function([B.number], B.number)
iex> TypeCheck.External.apply(type, Kernel, :abs, [-13])
{:ok, 13}
iex> {:error, err} = TypeCheck.External.apply(type, Kernel, :abs, [false])
iex> err.message
"At lib/type_check/external.ex:176:\n `false` is not a number."
@spec apply!(TypeCheck.Type.t(), module(), atom(), list()) :: any()
The same as Kernel.apply/3
but ensures that values conform the given type.
The first argument must be a function type of the function to be called.
In case of type error, raises an exception.
Examples
iex> alias TypeCheck.Builtin, as: B
iex> type = B.function([B.number], B.number)
iex> TypeCheck.External.apply!(type, Kernel, :abs, [-13])
13
iex> TypeCheck.External.apply!(type, Kernel, :abs, ["hello"])
** (TypeCheck.TypeError) At lib/type_check/external.ex:176:
`"hello"` is not a number.
Ensure at runtime that arguments at result of function call conform the function spec.
The function spec is extracted at compile time from the regular Elixir (or Erlang) @spec
.
Examples
iex> import TypeCheck.External
iex> enforce_spec!(Kernel.abs(-13))
13
iex> enforce_spec!(Kernel.abs("hi"))
** (TypeCheck.TypeError) At lib/type_check/external.ex:176:
`"hi"` is not a number.
@spec fetch_spec(module(), atom(), arity()) :: TypeCheck.Type.t()
Extract TypeCheck type from the regular Elixir (or Erlang) @spec
of the given function.
Examples
iex> import TypeCheck.External
iex> {:ok, type} = fetch_spec(Kernel, :abs, 1)
iex> type
#TypeCheck.Type< (number() -> number()) >
iex> {:ok, type} = fetch_spec(Atom, :to_string, 1)
iex> type
#TypeCheck.Type< (atom() -> binary()) >
iex> fetch_spec(Kernel, :non_existent, 1)
{:error, "cannot find spec for function"}
@spec fetch_type(module(), atom(), [TypeCheck.Type.t()]) :: TypeCheck.Type.t()
Extract TypeCheck type from the regular Elixir (or Erlang) @type
with the given name.
To fetch a generic type, you must pass a list of types to be placed instead of
generic variables. If you don't know these types, just punch in any()
as many times as you need. For example, to fetch the type of Range.t(left, right)
,
you need to pass [number(), number()]
or [any(), any()]
.
Examples
Fetching a regular type:
iex> import TypeCheck.External
iex> {:ok, type} = fetch_type(String, :t)
iex> type
#TypeCheck.Type< binary() >
Fetching a generic type:
iex> import TypeCheck.External
iex> import TypeCheck.Builtin
iex> {:ok, type} = fetch_type(:elixir, :keyword, [number()])
iex> type
#TypeCheck.Type< list({atom(), number()}) >
iex> {:ok, type} = fetch_type(Range, :t, [integer(), integer()])
iex> type
#TypeCheck.Type< %Range{first: integer(), last: integer(), step: pos_integer() | neg_integer()} >
Fetching non-existent type causes an error:
iex> import TypeCheck.External
iex> fetch_type(String, :non_existent)
{:error, "cannot find type with the given name"}