◷ Reading Time: 16 minutes
An expression is a combination of explicit values, variables, operators, and functions that are evaluated according to particular rules and then produce new values.
For evaluating an expression ExpressionEval should be used. If a variable is required an instance of VariableContainer must be passed.
An expression is the building block of writing rules and conditions. There are some other models (e.g., Decision Table) that support more expression formats as well as normal expressions.
Values
Value is an expression evaluating it will return the same result. The evaluation engine can process the following value types:
Type | Format | Sample |
String | “test string value” | |
Parameterized String | Prefix $ | $”test is {adj} cool” —> adj is a parameter of logic. |
Integer | Suffix i | 23i |
Decimal | Suffix m | 67m |
Double | Suffix d | 0d |
Long | Suffix l | 20l |
Boolean | true false | |
Undefined | null | |
DateTime | # date_time_string # | #23-04-2009 3:9 pm# |
DateTime with Format specifier | # date_time_string | formatter_string # | #23-04-2009 | dd-MM-yyyy# |
TimeSpan | #{day.hour:minute:second}# | #{3:45}# |
Array | [value1, value2,… ] | [1,2,’test’,4] |
Dictionary | { key1:value1, key2:value2… } | {person: {name:’Joe’, age:10}} |
Year
y: The year, from 0 to 99
yy: The year, from 00 to 99
yyy: The year, with a minimum of three digits
yyyy: The year as a four-digit number
Month
M: The month, from 1 through 12
MM: The month, from 01 through 12
MMM: The abbreviated name of the month
MMMM: The full name of the month
Day
d: The day of the month, from 1 through 31
dd: The day of the month, from 01 through 31
ddd: The day of the month, from 01 through 31
dddd: The full name of the day of the week
Hour
h: The hour, using a 12-hour clock from 1 to 12
hh: The hour, using a 12-hour clock from 01 to 12
H: The hour, using a 24-hour clock from 0 to 23
HH: The hour, using a 24-hour clock from 00 to 23
Minute
m: The minute, from 0 through 59
mm: The minute, from 00 through 59
Second
s: The second, from 0 through 59
ss: The second, from 00 through 59
AM/PM
t: The first character of the AM/PM designator
tt: The AM/PM designator
For example:
MM/dd/YYYY
shows the abbreviated name of the month, the day of the month, from 01 through 31 and the year as a four-digit number separated with /
Array
An array is a list that can hold multiple values. The list can be manipulated using collection functions.
An array can be initialized using Native Complex Value or array function.
Variables
Variables can be defined with a name,
- Short variable name: alphabetic numeric _ $
- x
- abc3
- point_x
- $value
- Long variable name: { variable name }
- {applicant name}
- {risk factor}
- {person’s father name}
Variables in different logic are defined as parameters. You can define them in the following types of rules and logic:
- Procedural rules
- Flow logic
- Validation rules
- Workflow logic
- Inference rules
- Decision
Operators
All the execution routing conditions in the rules and logic are based on expression evaluation. An expression is shown below:
Mathematical operators
Name | Sign | Sample |
Addition | + | 23+4 |
Subtraction | – | 2.1-5.76 |
Division | / | 914/74 |
Multiplication | * | 48*6 |
Reminder | % | 78%4 |
Power | ** | 2**8 |
Increment | ++ | x++ |
Decrement | – – | x- – |
Assignment operator
Name | Sign | Description | Sample | Version |
Assignment | = | Assign a value to a parameter. Parameter must exist in the current context. | x=y. GetCordinate().X/2 approved=true applicant.GetDoc(‘system’,true).IsValid=system.Validity | 8 |
Declare and Assign | := | Assign a value to a parameter. Parameter will be registered in the context if does not exist. | y := 23+x/345*pi() approved :=true | 8 |
Addition assignment | += | Adds the right side value to the variable and assigns the result to the same variable | x = 2 x += 3 result: x = 5 y = “Hello” y += ” World” result: y = “Hello World” | 8 |
Subtraction assignment | -= | Substracts the right side value from the variable and assigns the result to the same variable | x = 3 x -= 1 result: x = 2 y = 4 y -= 5 result: y = -1 | 8 |
Multiplication assignment | *= | Multiplies the right side value by the variable and assigns the result to the same variable | x = 3 x *= 1 result: x = 3 y = 4 y *= -5 result: y = -20 | 8 |
Division assignment | /= | Devides the variable by the right side value and assigns the result to the same variable | x = 50 x /= 5 result: x = 10 y = 26 y /= -2 result: y = -13 | 8 |
Remainder assignment | %= | Devides the variable by the right side value and assigns the remainder to the same variable | x = 10 x %= 4 result: x = 2 y = 23 y %= 5 result: y = 3 | 8 |
Null-coalescing assignment | ??= | Checks whether the variable is null. If it is null, assigns the right side value to the variable, if not, keeps the variable value | x = null x ??= 3 result: x = 3 y = “Hello” y ??= “Hi” result: y = “Hello” | 8.1 + |
Null-coalesce | ?? | Checks whether the variable is null | x = null x??5 result: 5 x = 3 x??5 result: 3 | 8.1 + |
Assignment operator format:
expression = expression
In this case, the left-hand-side expression must finish with a Property or Field of an object
variable = expression
Boolean operators
Name | Sign | Sample |
And | && and | (age<18) && (i>10) (age<18) and (i>10) |
Or | || or | (Age lt 15) || (Male==true) (Age lt 15) or (Male==true) |
Negate | ! | !(Age lt 15) |
Format: (LEFT-BOOLEAN-EXPRESSION) [boolean operator] (RIGHT-BOOEALN-EXPRESSION)
Please note you MUST use parentheses around both sides of a boolean operator to make sure you prioritize the evaluation on the left and right side of the boolean operator.
Comparing operators
Name | Sign | Sample |
Equality | == eq | Age==18 |
Inequality | != neq | Gender != Female |
Less than | < lt | (Age < 15) (Age lt 15) |
Smaller than or equal | <= le | (Age <= 15) (Age le 15) |
Greater than | > gt | (Age > 15) (Age gt 15) |
Greater than or equal | >= ge | (Age >= 15) (Age ge 15) |
Case insensitive
Name | Sign | Sample | Result |
Equality | === is | ‘test’===’TEST’ | true |
Inequality | !== isnt | ‘abcd’ !== ‘Abcd’ | false |
Priority operator
Sub-expression evaluation based on priority:
- Begin (
- End )
(1-risk)*applicantAge
Object members operators
Access to objects (variable) members:
- Method (.)
- Property (.)
- Indexer, Array, list item access ([) and (])
applicant.Age*applicant.CalculateRiskFactor("A")
Null-Aware Property
Properties and Fields of data can be null, and the normal .
throws exception.
If you want to handle that exception, you may need to have if, then, else as follows.
if person != null and person.Parent !=null and person.Parent.Name !=null then person.Parent.Name.Length else null
In FlexRule, to avoid repeating!= null
, you can use the accesses operator ?.
as follows which does the exact same thing in above if,then else expression.
person?.Parent?.Name?.Length
Condition operator
Inline condition operator
Name | Sign | Sample |
Condition | ? | |
Alternatives | : | 2.1-5.76 |
For example:
(3==4)?'this is cool':'what are you talking about?'
If-Then-Else
The alternative of an inline condition operator is to use if-then-else format:
if condition then result else other-result
For example, the above example can be written as:
if 3==4 then 'this is cool' else 'what are you talking about?'
Also, they can be nested:
if Product Type == 'STANDARD LOAN'
then 20.00d
else if Product Type == 'SPECIAL LOAN'
then 25.00d
else null
Methods
A Method is a procedure associated with an object. This is the interface an object presents to the outside world. When a variable parameter is defined that holds an object, then the method of the object can be called using. operator. Parentheses are required at the end of the method and input arguments are comma-separated.
Example: Assume x and b are defined parameters, the expression ‘x.Calculate(2i, b)’ calls Calculate method of the x and pass integer 2 and variable b as input arguments.
String to Expression
You can use the @
sign to get the value of an expression in String format.
For example, to generate the results
, we will be reading each value from keylist
and use them in zip function. There, in zip function, its parameter requires a string value. Therefore, we have added 'keylist[x]'
expression with a @
to retrieve its value.
keylist = ["a", "b", "c"] values = [1,2,3] results = zip(range(0,keylist|count())|select(x,{@'keylist[x]':values[x]})) results = { "a" : 1, "b" : 2, "c" : 3 }
This is another example:
Username= "John" Message = "Hello " + @'Username' Message = "Hello John"
Functions
Functions are expressions that relate inputs (arguments) to outputs (function result). There are two types of functions in FlexRule:
When a function is defined it has the format shown below:
FunctionName(p1, p2, p3, ...)
where p1, p2, p3… are the parameters of the function which during the usage the values (Arguments) have to be passed to those parameters.
Or a function may have no parameters at all
FunctionName()
In both cases, the function can return a value as a result of the call which can be stored in a parameter using an assignment operator.
parameter = Function(value1, value2, ...)
Functions are very similar to methods, but the difference is that these do not belong to any specific variable. They are global in the whole expression evaluation context. For example, let’s consider the following expression:
in(age, array(3,4,56,60,3,10))
As you can see in and an array is accepting arguments with parentheses. These are comma-separated, exactly like methods, but there is no. operator involved. Functions can be defined at the application/rule level and they are a way to extend the functionality at the expression evaluation level.
Check API for built-in functions.
Decision Table Expressions
In a Decision Table, there are some more expression formats that can be used to simplify the value-based rules. In general, when a value is entered in a data section of a Decision Table, it dynamically resolves its type based on the column type and template expression.
Type of Value | Sample | Expression description |
Negate | not: 2-3-4 | Prefix with not: |
String | blah blah blah | |
Explicit String | “blah blah blah” or ‘blah…’ | String quotes (double or single) |
Numbers | 23 or 4i or 3.4d | No prefix (all expression rules in above sections apply) |
Expression | : applicant.GetLastAttendanceDate() | : |
Range | [23, 45] (43, 50) [39;456) [1 .. 456) | Square brackets [] for inclusion and Parentheses exclusion in value ranges and they are comma (,) or semicolon (;) or double dot (..) split. |
Multi-Values | 12,3,4 34,3d,’string value’, true, var2.Length | Multi values are ‘,’ split. They can be a combination of different values and variable references. For example, in the second example, we have defined multiple values as 34 (integer number), 3.0 (decimal number), true (boolean value) and var2.Length (as Length property of a variable reference named var2)Note: Multi values must explicitly specify their types on each element separated by a comma. |
Contains/In | in {“VIC”, “SA”} | in { LIST } where LIST is a set of expression values separated by comma. |
Pipe
Pipes are types of functions that you can chain together and pass previous results to the next one.
Functions that are used with Pipe are called Monads.
|pipeName (arg1, arg2, arg3...)
For example, the result of people |count() is an integer that is the length of the people list. In this example, the count function receives people as its input and its result as a number (integer).
var list = new List<DecisionAgeTests.Person>()
{
new DecisionAgeTests.Person("arash", 38, DecisionAgeTests.Gender.Male),
new DecisionAgeTests.Person("Parsa", 6, DecisionAgeTests.Gender.Male),
new DecisionAgeTests.Person("Pooya", 3, DecisionAgeTests.Gender.Male),
new DecisionAgeTests.Person("Shah", 3, DecisionAgeTests.Gender.Female)
};
var vc = new VariableContainer();
vc.RegisterVariable("people", list);
var res = ExpressionEval.Default.Compute(vc, "people |count ()");
Assert.AreEqual(list.Count, (int)res);
XML
When you are working with XML-based data/information, you need to read and manipulate XML.
For more details, visit Xml API help
Comments
When it is required to add descriptions and comments to describe the expressions, there are multiple ways you can do this in FlexRule. This link contains more information on that.
A comment section must start with /*
and end with */
Learn more about adding Comments.
Examples
Here are a couple of examples with different types of expressions.
Calculation
(a+b)+(2 * c)-d
Comparison
a < 10
(a+b) gt 23
a<=(c+d)
Assignment
a = b + c
str = 'hello FlexRule expressions'
Storing the result of comparison into ‘r’
r = (b+c)<d
In the below expression, age will be declared at runtime and the value of 18
will be assigned.
age := 18
On assignment of properties, when the parameter is null, an empty object automatically will be created.
Person := null Person.Name = "ABC"
Method Call
When obj
is an object reference which is not null
a = obj.CalculateSum()+20-b
Access Value
In below example, obj
is an instance of an object
b = obj.Name + '-' + obj.Family
Evaluating Expression in Code
Here is an example of how you can evaluate an expression containing some variables:
Evaluating expressions on FlexRule:
x := 5
y := 'a test string'
result := (x lt 3) ? x : (x+y.Length)
Evaluating FlexRule’s expression using C#:
var variables = new VariableContainer();
variables.Compute("x := 5");
variables.Compute("y := 'a test string'");
var res = variables.Compute("result := (x lt 3) ? x : (x+y.Length)");
// res, variables["result"] are both equal to 18