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 newDate
objectlengthOf(arr, length)
- checks the length of an arrayisTrue(something)
- check if something === trueisFalse(something)
- check if something === falseisRegExp(something)
- check if something is aRegExp
isArray(something)
- check if something is anArray
isNumber(something)
- check if something is anNumber
isHash(something)
- check if something is strictly anObject
isObject(something)
- check if something is any type ofObject
isDate(something)
- check if something is aDate
isBoolean(something)
- check if something is aBoolean
isString(something)
- check if something is aString
isUndefined(something)
- check if something is aundefined
isDefined(something)
- check if something isDefined
isUndefinedOrNull(something)
- check if something is aundefined
ornull
isPromiseLike(something)
- check if something is a "promise" like (containingthen
,addCallback
,addErrback
)isFunction(something)
- check if something is aFunction
isNull(something)
- check if something isnull
isNotNull(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.