-
Notifications
You must be signed in to change notification settings - Fork 154
Custom Functions
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:
- The arguments to the function, as un-evaluated
Expression
objects - Any substitutions for variable values
- The
Evaluator
performing the evaluation. You should always prefer to use thisEvaluator
within the closure, rather than capturing the externalEvaluator
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.
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
.