Skip to content

Custom Functions

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

By default, DDMathParser will automatically recognize any "identifier" as a function, even if no such function is defined. For example, the following will happily become an Expression with no complaints:

let e = try Expression(string: "foo() + bar() - baz() * bip()")

Of course, this will fail to evaluate, unless you define what the foo, bar, baz, and bip functions are.

Custom functions are defined on Evaluator instances. A custom function has a set of names and a closure to perform the evaluation:

let foo = Function(name: "foo", evaluator: { (arguments: Array<Expression>, substitutions: Substitutions, evaluator: Evaluator) throws -> Double
    ...
})

The closure takes three arguments:

  1. The arguments to the function, as un-evaluated Expression objects
  2. Any substitutions for variable values
  3. The Evaluator performing the evaluation. You should always prefer to use this Evaluator within the closure, rather than capturing the external Evaluator instance within the closure.

When the function is evaluated, you'll either return a Double if the expression can be correctly evaluated, or throw if a critical error is encountered (such as the incorrect number of arguments, attempting to divide by zero, etc). The thrown error can be either the appropriate EvaluationError or a custom ErrorType of your own making.

After this, all you need to do is register the function with your Evaluator:

var evaluator = Evaluator()
try evaluator.registerFunction(foo)

Registering a function may throw an error if any of the names of the function collides with the name of any existing function.

Function Aliases

Some function names are really long, like hacovercosin. You can use the registerAlias(_:forFunctionName:) method on Evaluator to define new ways of recognizing functions. For example:

var evaluator = Evaluator()
try evaluator.registerAlias("hcvcs", forFunctionName: "hacovercosin")

Now this Evaluator would be able to evaluate hcvcs(42). This operation would throw an error if either hcvcs is already in use by another function, or there is no such function hacovercosin.