What a great project!
When I stumbled upon it, I actually went looking for somewhere to use it. 🥇
The way you use JavaScript features to make the rules feel more natural, is very cool.
The premise merging feature is a great optimization... except when it's unwanted :-)
Disclaimer: I'm not an expert with rules engines, so feel free to point out if my thinking about this all wrong.
Consider a (somewhat contrived) example of a collection of rules which each ensure that a required section of a dynamic document are present:
requiredSections.forEach((clazz) => {
rules.push(new Rule({
name: 'require ' + clazz,
when: [
(facts) => (! document.querySelector('div.' + clazz))
],
then: (facts) => {
appendSectionTemplate(sectionTemplates.get(clazz));
}
}));
})
You could have 8 required sections, but they will all hash to the same premise, and so only one of the 8 actions will fire, ever.
If I've not missed something and this is a valid concern, what about enhancing the API such that a premise could be a function or an array the first element of which would always be a function.
Something like:
[(facts) => (! document.querySelector('div.' + clazz)), clazz]
This would still allow for hashing of the premise, would not break any existing rules/code, and would only require changes to 2 lines of code.
RuleSet.register would need a 1 line change:
premise = new Premise({
...rule,
id: this.nextPremiseId(),
name: `${rule.name} / ${index}`,
when: Array.isArray(when) ? when[0] : when,
});
And to keep bad things from happening, the assert on line 36 of Rule.js would need to be:
this.when.reduce((acc, premise) => acc && (isFunction(premise) || (Array.isArray(premise) && isFunction(premise[0]))), true),
This would provide premise merging by default, but allow an override on an as needed basis.
If this sounds interesting, I would be happy to provide a PR.
Thoughts?
What a great project!
When I stumbled upon it, I actually went looking for somewhere to use it. 🥇
The way you use JavaScript features to make the rules feel more natural, is very cool.
The premise merging feature is a great optimization... except when it's unwanted :-)
Disclaimer: I'm not an expert with rules engines, so feel free to point out if my thinking about this all wrong.
Consider a (somewhat contrived) example of a collection of rules which each ensure that a required section of a dynamic document are present:
You could have 8 required sections, but they will all hash to the same premise, and so only one of the 8 actions will fire, ever.
If I've not missed something and this is a valid concern, what about enhancing the API such that a premise could be a function or an array the first element of which would always be a function.
Something like:
[(facts) => (! document.querySelector('div.' + clazz)), clazz]This would still allow for hashing of the premise, would not break any existing rules/code, and would only require changes to 2 lines of code.
RuleSet.register would need a 1 line change:
And to keep bad things from happening, the assert on line 36 of Rule.js would need to be:
this.when.reduce((acc, premise) => acc && (isFunction(premise) || (Array.isArray(premise) && isFunction(premise[0]))), true),This would provide premise merging by default, but allow an override on an as needed basis.
If this sounds interesting, I would be happy to provide a PR.
Thoughts?