Rule structure
Lets look at the "Calculate" rule in the Fibonacci example
Or using the nools DSL
Salience
Salience is an option that can be specified on a rule giving it a priority and allowing the developer some control over conflict resolution of activations.
Or using the DSL
In the above flow we define four rules each with a different salience, when a single message is asserted they will fire in order of salience (highest to lowest).
Scope
Scope allows you to access function from within your rules.
If you are using vanilla JS you can use the scope option when defining your rule.
If you are using the dsl.
Or you can pass in a custom function using the scope option in compile.
Provided the doesMatch function in the scope option of compile.
Constraints
Constraints define what facts the rule should match. The constraint is a array of either a single constraint (i.e. Bootstrap rule) or an array of constraints(i.e. Calculate).
Programmatically
Using nools DSL
Type - is the Object type the rule should match. The available types are
String- "string", "String", StringNumber- "number", "Number", NumberBoolean- "boolean", "Boolean", BooleanDate- "date", "Date", DateRegExp- "regexp", "RegExp", RegExpArray- "array", "Array", [], ArrayObject- "object", "Object", "hash", Object- Custom - any custom type that you define
Alias - the name the object should be represented as.
Pattern(optional) - The pattern that should evaluate to a boolean, the alias that was used should be used to reference the object in the pattern. Strings should be in single quotes, regular expressions are allowed. Any previously defined alias/reference can be used within the pattern. Available operators are.
&&,AND,and||,OR,or>,<,>=,<=,gt,lt,gte,lte==,===,!=,!==,=~,!=~,eq,seq,neq,sneq,like,notLike+,-,*,/,%-(unary minus).(member operator)in(check inclusion in an array)notIn(check that something is not in an array)- Defined helper functions
now- the current dateDate(year?, month?, day?, hour?, minute?, second?, ms?)- creates a newDateobjectlengthOf(arr, length)- checks the length of an arrayisTrue(something)- check if something === trueisFalse(something)- check if something === falseisRegExp(something)- check if something is aRegExpisArray(something)- check if something is anArrayisNumber(something)- check if something is anNumberisHash(something)- check if something is strictly anObjectisObject(something)- check if something is any type ofObjectisDate(something)- check if something is aDateisBoolean(something)- check if something is aBooleanisString(something)- check if something is aStringisUndefined(something)- check if something is aundefinedisDefined(something)- check if something isDefinedisUndefinedOrNull(something)- check if something is aundefinedornullisPromiseLike(something)- check if something is a "promise" like (containingthen,addCallback,addErrback)isFunction(something)- check if something is aFunctionisNull(something)- check if something isnullisNotNull(something)- check if something is not nulldateCmp(dt1, dt2)- compares two dates return 1, -1, or 0(years|months|days|hours|minutes|seconds)(Ago|FromNow)(interval)- adds/subtracts the date unit from the current time
Reference(optional) - An object where the keys are properties on the current object, and values are aliases to use. The alias may be used in succeeding patterns.
Custom Constraint
When declaring your rules progrmmatically you can also use a function as a constraint. The function will be called with an object containing each fact that has matched previous constraints.
Not Constraint
The not constraint allows you to check that particular fact does not exist.
Or using the DSL.
The previous example will check that for all numbers in the workingMemory there is not one that is greater than n1.
Or Constraint
The or constraint can be used to check for the existence of multiple facts.
Using the DSL.
The previous example will evaluate to true if you have a string in workingMemory that equals hello, world, or 'hello world.
Or with Not
The or constraint can be combined with a not constraint to allow for the checking of multiple not conditions without the implcit and.
or using the dsl.
Note Using the or with a not will cause the activation to fire for each not condition that passes. In the above examples if none of the three facts existed then the rule would fire three times.
From Constraint
The from modifier allows for the checking of facts that are not necessarily in the workingMemory.
The from modifier can be used to access properties on a fact in workingMemory or you can use javascript expressions.
To access properties on a fact you can use the fact name and the property you wish to use as the source for the from source.
Or using the DSL.
The above example will used the address, firstName and lastName from the person fact.
You can also use the from modifier to check facts that create a graph.
For example assume the person object from above has friends that are also of type Person.
Or using the DSL.
The above example will pull the friend fact from the friends array property on fact p, and first from the friend's firstName.
You could achieve the same thing using the following code if you assert all friends into working memory.
To specify the from source as an expression you can do the following.
Or using the dsl
Using the above syntax you could use from to bootstrap data.
You can also use any function defined in the scope of the rule or flow
Or using the dsl and the scope option.
Exists Constraint
exists is the logical inversion of a not constraint. It checks for the existence of a fact in memory.
NOTE If there are multiple facts that satisfy the constraint the rule will ONLY be fired once.
Or using the DSL.
Assuming the above constraint. The following facts would cause the rule to fire once since there is a number that is greater than 1.
Action
The action is a function that should be fired when all patterns in the rule match. The action is called in the scope
of the engine so you can use this to assert, modify, or retract facts. An object containing all facts and
references created by the alpha nodes is passed in as the first argument to the action.
So calculate's action modifies f3 by adding the value of f1 and f2 together and modifies f3 and retracts f1.
The session is also passed in as a second argument so alternatively you could do the following.
To define the actions with the nools DSL
For rules defined using the rules language nools will automatically determine what parameters need to be passed in based on what is referenced in the action.
Async Actions
If your action is async you can use the third argument which should be called when the action is completed.
If an error occurs you can pass the error as the first argument to next.
If you are using a Promises/A+ compliant library you can just return a promise from your action and nools will wait for the promise to resolve before continuing.
Globals
Globals are accessible through the current working scope of rules defined in a dsl, very similar to using the scope option when compiling.
Note globals are not part of the working memory and therefore are not accessible in the LHS (when) or your rule.
Globals are used like the following:
If you are using nools in node you can also use a require statement.
NOTE require does not currently work for relative paths.
Importing
The import statement allows you to import other nools files into the current one. This can be used to split up logical flows into small reusable groups of rules.
Define our common model to be used across our flows.
Create a rules file which imports the define.nools to define our Count model.
Same as orRule.nools import our define.nools
Now we can use orRule.nools and notRule.nools to compose a new flow that contains define.nools, orRule.nools and notRule.nools.
Note nools will handle duplicate imports, in this case define.nools will only be imported once.