Skip to content

Dynamic Resolution

Dave DeLong edited this page Sep 19, 2015 · 3 revisions

Overriding Functions

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 appropriate ErrorType
  • If you do not wish to participate in the overriding of this particular function evaluation, return nil. If you return nil, the default function evaluation will continue.

There are two important things to note about overriding functions:

  1. This overrideFunction(...) method will be called for every function in an Expression tree. If you only want to override a single method, check the function parameter for the appropriate name, and otherwise return nil.

  2. 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.

Function Resolution

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.

Variable Resolution

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.