Operator Type:
Operator Scope of Action:
Operator Purpose:
Operator First Added:
Operator Altered:
Function [other Function type actions]
Conditional Group [operators of similar scope]
Data manipulation [other Data manipulation operators]
Baseline
In rules and (agent) actions, Tinderbox uses this conditional action syntax:
if(expression) { action-list }
if (expression) {action-list} else {action-list}
Where:
- expression is any action code involving an evaluation to a conditional test that resolves to a Boolean true (if the condition is as expected). If the expression is in the form of an $Attribute(pattern) query, regex back-references can be used in in the action code of the action-list. A conditional expression can also be a query, such as find(), where matching zero results is a 'false' and otherwise a 'true' is returned.)
- action-list is a list of one or more assignment statements or stamps, separated by semicolons.
Example:
if($ChildCount>5) {$Color="red";$Width=3.5} else {$Color="blue"}
A condition can have multiple tests. And (&) or Or (I) joins are allowed as is parenthesised nesting of expressions:
if($ChildCount>5 | $Badge="ok") { $Color="red";$Width=3.5}
if(($ChildCount>5 & $Badge="ok") | $WordCount >= 450) { $Color="red";$Width=3.5}
If the expression is a complex set of condition clauses it may make sense to calculate the conditions, store the value in a attribute and test that in the if(0. This form of re-writing the test is a normal part of incremental formalisation such as may occur as a document gets bigger and more complex.
Negative tests
The testing for negatives, the absence of a value (or being in default condition), may be done in several ways. For an attribute value test, the attribute name may simply be prefixed with an exclamation mark, using the short form Boolean test:
if(!$MyString){…etc.
Otherwise the != operator is used:
if($MyString!="some value"){…etc.
Closing statements
It is not necessary to close the (last) action code statement in an action list, i.e. put a semi-colon before the closing '}'. However, a semi-colon closure is required after the last closing '}' if other action code follows within the same rule or action:
if($ChildCount>5) {$Color="red";$Width=3.5} else {$Color="blue"}; $Badge="ok";
if(!$MyString) {
$Color="red"
} else {
$Color="blue";
};
$WordCount(parent) = $WordCount(parent) + $WordCount
Testing multiple conditions
Whilst a single if() test can use a complex expression to form its conditional test, it may be necessary to run a set of linked tests. However, there is no 'else if' construct as found in many programming languages. To handle more than two branches to a condition test, nest an additional if() in either action-list of the first test. Thus:
if(!$MyString) {
…
} else {
if($MyBoolean) {
…
} else {
if($MyNum > 2) {
…
} else {
…
}
}
}
In the example above there are two nested if tests within the original if(). Note how nesting is achieved. It is probably more normal that the additional if goes in the 'else' branch of the preceding condition but that is not a requirement - it can be in either branch according to the needs of the scenario. Indeed, both branches of an if could in theory hold another if().
However, this form of coding can quickly get complex and care should be taken with placing appropriate '}' closures. In complex branching, consider using additional queries to hold some initial levels of test, rather than do everything in a complex nested call.
Backreferences
Back-references found by regular expression matches in operators like .contains() are available in if() clauses. For example, the rule:
if($Name.contains("a(..)") ) {$MyString=$1}
will now set $MyString to "pp" if $Name is "apple", or to "rs" if $Name is "pears". Note that the $0 back-reference contains the full matched expression.