RuleAPI:Natural Language

From FlexRule Wiki
(Redirected from RuleAPI:NL)
Jump to: navigation, search

Natural Language

Natural Language (NL) is a language to model business rules close to your spoken language. The intends to remove all the noise that an XML models has, and emphases on the actual business rules using business glossary, terms and logic that are reusable across other types of logic.

As the results rule are much more simpler to understand with less nose related to structure and/or types of the rule logic.


@name test a person identity

input person    
output valid

when Person has identity
    Person has name or
    Person has family
    ) and
    Email of person match "\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*"
    /* Birth city must be available */
     Name of City of BirthPlace of person is not null and
     Name of City of BirthPlace of person is not empty
    ) or
    Age of person lt 18
   set valid to true

when Person has name
        Name of person is not null and
        Name of person is not empty

when Person has family
        Family of person is not null and
        Family of person is not empty



The body of rule, contains

  1. the name of the rule
  2. context
  3. set of logic
@name "name of rule document"
/* enable attribute is not mandatory, if it’s not set the default value will be added automatically. Default value is true. */
@enable {true | false} 


{logic 1}
{logic 2}
{logic n}


A logic is a when-then-otherwise-end block. then and otherwise are optional.

/* There might be one or more when condition available in the rule document */
when {name of logic}
    {Body of condition}
    {body of actions}  
    {body of actions}  

Please note a logic can have no name. In this case remove {name of logic} from after when.

When {body of condition} is left empty, the actions on then automatically will be executed. If the {body of condition} is provided, then will be executed when {body of condition} are met otherwise the otherwise will be executed.

Parameterised Logic

In defining logic with parameters, { and } are used that enclose the parameter name

/*A logic with parameter named amount*/
when Add bonus of {amount} to total amount

/*A logic with NO parameters*/
when Print total

In calling a logic, just use its name. If the logic is parameterised then ( and ) are used to pass values

    Add bonus of (12.3) to total amount   and
    Print total
Note pinned.png ( and ) are mandatory to call the parameterised logic.


Adding {context} to rules has the following format:

/* List of input parameters */
 given | input variable1, variable2, …
 /* List of output parameteres */
 output variable1, variable2, …

Body of condition

{Body of condition} has the following format:

{compare expression-1} {or|and|nor|xor|xnor}
{compare expression-2} {or|and|nor|xor|xnor}
{compare expression-n} 
/* Or may contains groups or nested groups. Group starts with ( and ends with ) */
    {Body of condition-1} {or|and|nor|xor|xnor}
    {Body of condition-2} {or|and|nor|xor|xnor}
    {Body of condition-n} 
) {or|and|nor|xor|xnor}
{Body of condition}

Compare expression

{compare expression} has the following format:

case 1: {left hand expression} {operator} {right hand expression}
case 2: name of logic
case 3: Any expression
case 1

{Right hand expression} can be any expression or {Value}.

{operator} can be

  1. Comparison operators
  2. Or any of: is, is not, match, not match

{left hand expression} can be a {term} or can be any expression or {Value}.

case 2

When multiple logic is defined in a document, the can have a name and call each other by name. In these cases, the parameter can be called by parentheses.

When multiple actions are expected as part of the consequence, then they should be separated or connect by either of the following:

  • and
  •  ; (semicolon)
  • set


Value can be primitive, constant values or complex expressions. e.g. value [3; 45] is a range expression value.

{value} can be any Expression
Of Operator
{left or right hand expression} may have:
/* Flat property access */
{Property name} of {variable}
/* Or nested property access */
{Property name} of {Property name} of {Property name} of … {variable}


Logic with names:


Logic with no name:


Where r1, r2, r3, r4, and r5 are some other logic that are used in this logic.


If you need to iterate on a list (i.e. array, or collection of objects) you can use for.

for variableName in listName
  /* do your tasks */

When there is a condition to break the iteration, you include until to the for.

for variableName in listName until (expression)
  /* do your tasks */

The loop executes while the evaluated expression is false.


Comments can be added to the rule document using /* and */.




Parameters can be defined in standard way using Declaration section or inside the Dsl section.

Or alternatively they can be defied as part of the NL with the following keywords:

  1. input: defines input parameters.
  2. give: defines input parameters.
  3. output: defines output parameters.


[input|give|output] list of parameters, separated by comma



Local Parameters

Local [Parameter]s can be added in two different levels:

  1. Root scope
  2. Logic scope

In the bellow example 'g' is defined as a local parameters in the logic scope.

when split {names} into groups
    /* defining a local parameter in a Logic scope. */
    local g;
    g = split(names,',');

    /* rest of your logic */


In the body of logic, all the operators that are described in Expression section are accepted. On top of that, there are some specific operators in NL as follow:

  1. is: To check equality
  2. is not: To check inequality
  3. match: To check Regex pattern is matched
  4. match not: To check Regex pattern is not matched
  5. of: access to field and property on a parameter
  6. set/to: set a value to parameter or its underlying structure. An alias to Val.



[value|parameter|Term] [match | not match] pattern


Email of person match ""\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*""

where Email is a property on person parameter.


Boolean expressions can be chained in the body of logic.


exp = [boolean value | term [is|is not] value | boolean expression] 
condition = exp [and|or|nor|xor] | exp... 


Sample 1

A rule lik this:

R4: If all of the following are true, then the car’s potential theft rating is *low*.
	* car model is *not* on HTPA list
	* car’s price is between $20,000 and $45,000,

can be modelled as bellow:


Sample 2

In this example, we need to produce the result bellow(right) from a source(left):


We have two questions to answer:

  1. Cars in both groups (commonCars)
  2. Unique cars in each group (allUniqueCars)

input cars
commonCars: cars in both groups
allUniqueCars: unique cars in each groups
output commonCars, allUniqueCars 

local g1,g2,ab,ba,groups  

when main 
	split into groups; 
	/* Intersect of two groups */
	commonCars = g1 
		     |select(x, x.Make, x.Model) 
		     |intersect (
			g2 |select(x, x.Make, x.Model)
	/* difference of first group from second one */
	ab = g1
	     |select (x, x.Make, x.Model) 
	     |except (
		g2 |select (x, x.Make, x.Model)
	/* difference of second group from first one*/
	ba = g2
	     |select (x, x.Make, x.Model) 
	     |except (
		 g1 |select (x, x.Make, x.Model)

	/* union the differences */
	allUniqueCars = ab |union (ba);
when split into groups
        /* As you see here, it allows you to split the logic
        and then you call it later by its name */ 
	groups = cars |groupBy (x, x.Group);
	g1 = groups[0];
	g2 = groups[1];

Sample 3: Auto premium

Calculation of auto premium of a car in Natural Language:Add bonus of (12.3) to total amount

input car

when main
@processAll false

	test for Compact or
	test for Sedan or
	test for Luxury

when test for Compact
	(car.Style != 'Compact') or ((car.Model == 'abcd') and (car.ModelYear == 1999)) or
	car.ModelYear == 2002
	increase premium by (250) amount

when test for Sedan
	increase premium by (400) amount

when test for Luxury
	increase premium by (500) amount

when increase premium by {n} amount
	car.AutoPremium += n;


In NL document, $context can be used to write notifications.

Format: $context.WriteInfo(groupName, message)
        $context.WriteWarning(groupName, message)
        $context.WriteError(groupName, message)
  • groupName: to categorize a set of notices in notification collection. null when it is not needed.
  • message: any text, expression or value for the notice
Example: $context.WriteError(null, '$Assets is imputed.');

The other option is to use notification functions


Inference capability allows rules dependencies to each other within on ruleset be resolved at runtime. Which means order of rules definition becomes irrelevant to the order of rules execution. Ro use inference command run on can be used:

run goal on {r1, r2, r3...}
  • goal (optional): name of the parameter that is the goal to be answered
  • r1,r2...: name of the rules i.e. when names
Bulbgraph.pngWhen a goal is specified, only the rules related to that goal will be included in the execution rule set. Extra rules will be filter out. If all the rules in the set must be executed, you can omit the goal.


when main
    run on {test for Compact, test for Sedan, test for Luxury}