View Source Croma.Defun (croma v0.11.3)

Module that provides Croma.Defun.defun/2 macro.

Link to this section Summary

Functions

Defines a function together with its typespec.

Defines a private function together with its typespec.

Defines a unit-testable private function together with its typespec.

Link to this section Functions

Link to this macro

defun(arg1, arg2)

View Source (macro)

Defines a function together with its typespec.

This provides a lighter-weight syntax for functions with type specifications and functions with multiple clauses.

example

Example

The following examples assume that Croma.Defun is imported (you can import it by use Croma).

defun f(a :: integer, b :: String.t) :: String.t do
  "#{a} #{b}"
end

The code above is expanded to the following function definition.

@spec f(integer, String.t) :: String.t
def f(a, b) do
  "#{a} #{b}"
end

Function with multiple clauses and/or pattern matching on parameters can be defined in the same way as case do ... end:

defun dumbmap(as :: [a], f :: (a -> b)) :: [b] when a: term, b: term do
  ([]     , _) -> []
  ([h | t], f) -> [f.(h) | dumbmap(t, f)]
end

is converted to

@spec dumbmap([a], (a -> b)) :: [b] when a: term, b: term
def dumbmap(as, f)
def dumbmap([], _) do
  []
end
def dumbmap([h | t], f) do
  [f.(h) | dumbmap(t, f)]
end

pattern-matching-on-function-parameter-and-omitting-parameter-s-type

Pattern matching on function parameter and omitting parameter's type

If you omit parameter's type, its type is infered from the parameter's expression. Suppose we have the following function:

defun f(%MyStruct{field1: field1, field2: field2}) :: String.t do
  "#{field1} #{field2}"
end

then the parameter type becomes MyStruct.t.

@spec f(MyStruct.t) :: String.t
def f(a1)
def f(%MyStruct{field1: field1, field2: field2}) do
  "#{field1} #{field2}"
end

generating-guards-from-argument-types

Generating guards from argument types

Simple guard expressions can be generated by defun/2 using g[type] syntax. For example,

defun f(s :: g[String.t], i :: g[integer]) :: String.t do
  "#{s} #{i}"
end

is converted to the following function with when is_integer(i) guard.

@spec f(String.t, integer) :: String.t
def f(s, i)
def f(s, i) when is_binary(s) and is_integer(i) do
  "#{s} #{i}"
end

For supported types of guard-generation please refer to the source code of Croma.Guard.make/3.

Guard generation can be disabled by setting application config at compile time. For example, by putting the following into config/config.exs,

config :croma, [
  defun_generate_guard: false
]

then g[String.t] becomes semantically the same as String.t.

validating-arguments-and-return-value-based-on-their-types

Validating arguments and return value based on their types

You can instrument check of pre/post conditions by specifying type as v[type]. For instance,

defmodule MyString do
  use Croma.SubtypeOfString, pattern: ~r/^foo|bar$/
end

defun f(s :: v[MyString.t]) :: atom do
  String.to_atom(s)
end

becomes the following function definition that calls valid?/1 at the top of its body:

@spec f(MyString.t) :: atom
def f(s)
def f(s) do
  if !MyString.valid?(s) do
    raise "..."
  end
  String.to_atom(s)
end

The generated code assumes that valid?/1 function is defined in the type module of the specified type. For primitive types croma defines their type modules and thus you can freely use e.g. v[integer].

Generating validation of arguments and return values can be disabled by setting application config during compilation.

config :croma, [
  defun_generate_validation: false
]

known-limitations

Known limitations

  • Overloaded typespecs are not supported.
  • Guard generation and validation are not allowed to be used with multi-clause syntax.
  • Using unquote fragment in parameter list is not fully supported.
  • try block is not implicitly started in body of defun, in contrast to def.
Link to this macro

defunp(arg1, arg2)

View Source (macro)

Defines a private function together with its typespec.

See defun/2 for usage of this macro.

Link to this macro

defunpt(arg1, arg2)

View Source (macro)

Defines a unit-testable private function together with its typespec.

See defun/2 for usage of this macro. See also Croma.Defpt.defpt/2.