-
Notifications
You must be signed in to change notification settings - Fork 0
The Math Evaluator
Evaluation is part of the expression's logic, but it uses the Math Evaluator quite extensively.
Evaluating a number expression is trivial. It simply returns the underlying NSNumber
object.
Evaluating a variable is also relatively straight-forward. First, the variable is looked up in the passed substitutions dictionary. If no replacement is found, then an error is generated and evaluation aborts.
Otherwise, the object is examined:
- if the substitution value is another expression, that expression is evaluated and its return value becomes the variables value.
- if the substitution value is a string, that string is evaluated as an expression, and its return value becomes the variables value
- if the substitution value is a number, the number is used directly
- any other substitution value generates an error
Evaluating a function is where the math evaluator is used. The expression asks the evaluator for a DDMathFunction
(a block) that matches the name of the function. If no match is found, a failure method is invoked on the evaluator (-functionExpressionFailedToResolve:error:
), which generates an error and aborts evaluation.
Otherwise, the DDMathFunction
is invoked with four arguments:
- the array of
DDExpression
objects that are the arguments to the function - the substitution dictionary
- the math evaluator
- the
NSError**
(for reporting errors)
The return value of the DDMathFunction
should be another DDExpression
object, although some leniency is allowed: NSNumbers
are returned directly and NSStrings
are parsed and evaluated to extract a numerical value.
The math evaluator allows you to specify the unit in which angles are measured. The two options are DDAngleMeasurementModeRadians
(the default) and DDAngleMeasurementModeDegrees
.
When the measurement mode is in radians, the following is true:
sin(π/2) = 1
asin(0.7071067811865475) = .785398163
sin(45) = 0.8509035245341184
However, the when measurement mode is in degrees, the evaluation changes:
sin(π/2) = 0.02741213359204429
asin(0.7071067811865475) = 45
sin(45) = 0.7071067811865475
DDMathEvaluator
has two properties that allow you to lazily resolve functions and variables: functionResolver
and variableResolver
.
Lazy function resolution can be very handy when using DDMathParser
to process user-generated input. For example, you can use lazy function resolution to process a string like this:
"age/2 + 7"
According to the rules of argumentless functions, this will be parsed as:
(age() / 2) + 7
The advantage of this is that users do not need to understand the syntax for variables and their need for the leading $
character.
By specifying the appropriate block for the functionResolver
, you can process these functions as if they were variables. The Demo in the repository contains an example of a function resolver.
Like with functions, you can specify a block to lazily resolve unknown variables. The block, however, is much simpler: it takes a single string argument (the name of the variable) and returns an NSNumber
.