A function is a predicate with an arguments list.
For more information on being a predicate, see Ash.Filter.Predicate. Most of the complexities
are there. A function must meet both behaviours.
Summary
Callbacks
The number and types of arguments supported.
Whether or not the function return nil.
Whether or not the function can be evaluated eagerly. For example, now() cannot be.
Evaluate a function when all arguments are known valid values
If true, will be allowed to evaluate nil inputs.
The name of the function
Instantiate a new function with the provided arguments
Evaluate a function when some or no arguments are known valid values
Whether or not the function is a predicate (takes a reference as the first argument, a value as the second, and returns a boolean)
Whether or not the function should be usable when parsing input.
The return type for each corresponding set of args.
Functions
Whether an expression's type is compatible with a declared argument type.
Evaluate the operator with provided inputs
Attaches the appropriate suffix to refer to an ordinal number, e.g 1 -> "1st"
Casts args to a single declared signature, returning the cast list or nil.
Types
@type arg() :: any()
Callbacks
@callback args() :: [arg()] | :var_args
The number and types of arguments supported.
Whether or not the function return nil.
@callback eager_evaluate?() :: boolean()
Whether or not the function can be evaluated eagerly. For example, now() cannot be.
Evaluate a function when all arguments are known valid values
@callback evaluate_nil_inputs?() :: boolean()
If true, will be allowed to evaluate nil inputs.
If false (the default), any nil inputs will cause a nil return.
@callback name() :: atom()
The name of the function
@callback new([term()]) :: {:ok, term()} | {:error, String.t() | Exception.t()}
Instantiate a new function with the provided arguments
Evaluate a function when some or no arguments are known valid values
@callback predicate?() :: boolean()
Whether or not the function is a predicate (takes a reference as the first argument, a value as the second, and returns a boolean)
@callback private?() :: boolean()
Whether or not the function should be usable when parsing input.
@callback returns() :: [Ash.Type.t() | {Ash.Type.t(), constraints :: Keyword.t()}] | Ash.Type.t() | {Ash.Type.t(), constraints :: Keyword.t()} | :unknown
The return type for each corresponding set of args.
Functions
Whether an expression's type is compatible with a declared argument type.
Vague declarations (:any, :same and their array forms) accept anything.
A concrete declaration matches when the expression's type, as resolved by
Ash.Expr.determine_type/1, is that type or acts as it: a NewType acts as
its subtype_of, and any type may name another via Ash.Type.acts_as/1
(an :atom acts as a :string, an embedded resource acts as a :map, and
so on), recursively. Functions should therefore declare the most general
type they accept: datetime_add/3 declares :datetime, so any datetime
NewType such as :utc_datetime_usec is accepted. An expression whose type
cannot be determined is considered compatible, as there is no evidence
against it.
Evaluate the operator with provided inputs
Attaches the appropriate suffix to refer to an ordinal number, e.g 1 -> "1st"
Casts args to a single declared signature, returning the cast list or nil.
With exact?: true, a value only fits a declared type if casting leaves it
unchanged, so signatures are matched on the type the value already has.