plymio_codi v0.3.1 Plymio.Codi.Pattern.Bang View Source
The bang patterns builds bang functions
(e.g. myfun!(arg)) using existing base functions (e.g. myfun(arg)).
When the base function returns {:ok, value}, the bang
function returns value.
If the base function returns {:error, error}, the error is raised.
Bang functions can be built with, optionally, with a @doc, @since
and/or @spec.
See Plymio.Codi for an overview and documentation terms.
Note if the base function is in another module, the base mfa
{module, function, arity} is validated i.e. the function must
exist in the module with the given arity.
If :fun_doc is not in the pattern opts, a default of :bang is
used. (It can be disabled by explicitly setting :fun_doc to
nil)
Pattern: bang
Valid keys in the cpo are:
| Key | Aliases |
|---|---|
:bang_module | :module, :fun_mod, :bang_module, :function_module |
:bang_name | :name, :fun_name, :function_name |
:bang_args | :args, :fun_args, :function_args |
:bang_arity | :arity, :fun_arity, :function_arity |
:bang_doc | :doc, :fun_doc, :function_doc |
:spec_args | |
:spec_result | :result, :fun_result, :function_result |
:since |
Examples
Here is the common case of a bang function for a function in the
same module. Note the automatically generated :bang-format @doc
and explicitly specified @since:
iex> {:ok, {forms, _}} = [
...> bang: [as: :fun_tre, arity: 3, since: "1.7.9"]
...> ] |> produce_codi
...> forms |> harnais_helper_format_forms!
["@doc \"Bang function for `fun_tre/3`\"",
"@since \"1.7.9\"",
"def(fun_tre!(var1, var2, var3)) do",
" case(fun_tre(var1, var2, var3)) do",
" {:ok, value} ->",
" value",
"",
" {:error, error} ->",
" raise(error)",
" end",
"end"]
Here the other function is in a different module(ModuleA):
iex> {:ok, {forms, _}} = [
...> bang: [as: :fun_tre, arity: 3, to: ModuleA, since: "1.7.9"]
...> ] |> produce_codi
...> forms |> harnais_helper_format_forms!
["@doc \"Bang function for `ModuleA.fun_tre/3`\"",
"@since \"1.7.9\"",
"def(fun_tre!(var1, var2, var3)) do",
" case(ModuleA.fun_tre(var1, var2, var3)) do",
" {:ok, value} ->",
" value",
"",
" {:error, error} ->",
" raise(error)",
" end",
"end"]
The :fun_args can be supplied to improve the definition. Note the :fun_doc is set to false.
iex> {:ok, {forms, _}} = [
...> bang: [as: :fun_tre, args: [:x, :y, :z], to: ModuleA, fun_doc: false]
...> ] |> produce_codi
...> forms |> harnais_helper_format_forms!
["@doc false", "def(fun_tre!(x, y, z)) do",
" case(ModuleA.fun_tre(x, y, z)) do",
" {:ok, value} ->",
" value",
"",
" {:error, error} ->",
" raise(error)",
" end",
"end"]
Similary, if the cpo contains a :spec_result key, a @spec will
be generated. The second example has an explicit :spec_args
iex> {:ok, {forms, _}} = [
...> bang: [as: :fun_tre, args: [:x, :y, :z], module: ModuleA, result: :tuple]
...> ] |> produce_codi
...> forms |> harnais_helper_format_forms!
["@doc \"Bang function for `ModuleA.fun_tre/3`\"",
"@spec fun_tre!(any, any, any) :: tuple",
"def(fun_tre!(x, y, z)) do",
" case(ModuleA.fun_tre(x, y, z)) do",
" {:ok, value} ->",
" value",
"",
" {:error, error} ->",
" raise(error)",
" end",
"end"]
iex> {:ok, {forms, _}} = [
...> bang: [as: :fun_tre, args: [:x, :y, :z], module: ModuleA,
...> spec_args: [:integer, :binary, :atom], result: :tuple]
...> ] |> produce_codi
...> forms |> harnais_helper_format_forms!
["@doc \"Bang function for `ModuleA.fun_tre/3`\"",
"@spec fun_tre!(integer, binary, atom) :: tuple",
"def(fun_tre!(x, y, z)) do",
" case(ModuleA.fun_tre(x, y, z)) do",
" {:ok, value} ->",
" value",
"",
" {:error, error} ->",
" raise(error)",
" end",
"end"]
Pattern: bang_module
The bang_module pattern builds a bang function for one or more
functions in a module. As with :bang a @doc or @since can be generated at
the same time.
Valid keys in the cpo are:
| Key | Aliases |
|---|---|
:bang_module | :to, :module, :fun_mod, :fun_module, :function_module |
:bang_doc | :doc, :fun_doc, :function_doc |
:take | |
:drop | |
:filter | |
:reject | |
:since |
Examples
Here a bang function will be generated for all the functions in the module.
iex> {:ok, {forms, _}} = [
...> bang_module: [module: ModuleA],
...> ] |> produce_codi
...> forms |> harnais_helper_format_forms!
["@doc \"Bang function for `ModuleA.fun_due/2`\"",
"def(fun_due!(var1, var2)) do",
" case(ModuleA.fun_due(var1, var2)) do",
" {:ok, value} ->",
" value",
"",
" {:error, error} ->",
" raise(error)",
" end",
"end",
"@doc \"Bang function for `ModuleA.fun_one/1`\"",
"def(fun_one!(var1)) do", " case(ModuleA.fun_one(var1)) do",
" {:ok, value} ->",
" value",
"",
" {:error, error} ->",
" raise(error)",
" end",
"end",
"@doc \"Bang function for `ModuleA.fun_tre/3`\"",
"def(fun_tre!(var1, var2, var3)) do",
" case(ModuleA.fun_tre(var1, var2, var3)) do",
" {:ok, value} ->",
" value",
"",
" {:error, error} ->",
" raise(error)",
" end",
"end"]
In the same way as :delegate_module the functions can be selected
using e.g. :take. Here :since is also given.
iex> {:ok, {forms, _}} = [
...> bang_module: [module: ModuleA, take: :fun_due, since: "1.7.9"],
...> ] |> produce_codi
...> forms |> harnais_helper_format_forms!
["@doc \"Bang function for `ModuleA.fun_due/2`\"",
"@since \"1.7.9\"",
"def(fun_due!(var1, var2)) do",
" case(ModuleA.fun_due(var1, var2)) do",
" {:ok, value} ->",
" value",
"",
" {:error, error} ->",
" raise(error)",
" end",
"end"]