-
Notifications
You must be signed in to change notification settings - Fork 154
Dynamic Resolution
With a custom Evaluator
object, you can override the built-in implementation of any function. To do so, you would need a value that adopts the FunctionOverrider
protocol (declared in DynamicResolution.swift
).
This protocol defines a single method:
func overrideFunction(function: String, arguments: Array<Expression>, substitutions: Substitutions, evaluator: Evaluator) throws -> Double?
This takes all of the same arguments as a custom function, as well as the name of the function being evaluated. The return value of this method has different semantics than the return value of a custom function (since it returns Double?
and not Double
):
- If you can successfully evaluate the function, then return a
Double
- If an error occurs during evaluation,
throw
the appropriateErrorType
- If you do not wish to participate in the overriding of this particular function evaluation, return
nil
. If you returnnil
, the default function evaluation will continue.
There are two important things to note about overriding functions:
-
This
overrideFunction(...)
method will be called for every function in anExpression
tree. If you only want to override a single method, check thefunction
parameter for the appropriate name, and otherwise returnnil
. -
The function name passed in as the first parameter is not normalized. It is the function name as it appears in the string, without resolving aliases or standardizing on capitalization.
Getting a callback for every single function evaluation can be overkill. If you simply want to supply a value for a function when it's evaluated, provide a FunctionResolver
to your custom Evaluator
to get invoked after built-in and registered functions have failed to supply a value for a function. In this case, the name provided to the FunctionResolver
is normalized: if your Evaluator
is not case-sensitive, the name will be entirely lowercased; otherwise it will be the literal value in the original string.
Like with overriding functions, you have the ability to provide a value, throw an error, or return nil
.
Typically, variable values are supplied up-front as evaluation begins, by passing in a lookup dictionary.
However, you can also provide a VariableResolver
value to your custom Evaluator
to dynamically supply variable values as variable expressions are evaluated.