我认为是,但是我不太确定。
例如:
class Person {
int age;
int salary;
int bonus;
//getter and setter
public int calcIncome () {
return salary + bonus;
}
}
博士升:
when
$p:Person(age > 30, calcIncome() > 1000)
then
...
是否等于:
if (person.getAge() > 30 && person.calcIncome() > 1000) {
...
}
因此,当一个人的年龄不大于30岁时,calcIncome方法将不会被评估?
谢谢!
最佳答案
我自己做了一些测试,这就是我发现的(至少在6.3版中)。
针对Drools中特定规则的RETE算法的alpha子网始终按顺序进行评估。节点的顺序似乎是约束在它们所属的模式中具有的顺序。因此,我们可以说存在隐式短路机制。
顺便说一句,我没有发现逗号“,”或“ &&”之间的区别。在两种情况下,Drools都将表达式视为2个单独的alpha节点。
这是我所做的:
模型
public class Person {
private int age;
private int salary;
private int bonus;
public Person(int age, int salary, int bonus) {
//set values
}
public int calcIncome() {
throw new IllegalStateException("Expected error here!");
}
//getters
}
请注意,我是如何故意在
calcIncome()
中引发异常。规则A
该规则使用“ &&”表示
Person
模式的2个约束之间的AND运算。同样,通过使用逗号而不是“&”号也得到了相同的结果。
博士升
rule "Rule A"
when
$p:Person(age > 30 && calcIncome() > 1000)
then
System.out.println("Rule A");
end
RETE网络
优先规则的Rete网络如下所示:
在上图中,我们可以看到2个不同的alpha节点(黄色)。因为alpha节点是按顺序评估的,所以在这种情况下,如果我们评估的
Person
超过30年,则仅评估第二个节点。使用具有超过30年且少于30年的
Person
实例进行的测试证实了这一点:具有30年以上的实例会引发calcIncome()
的异常。规则B
然后,我很好奇当我们使用and或(||)运算符而不是and时会发生什么。
博士升
rule "Rule B"
when
$p:Person(age > 30 || calcIncome() > 1000)
then
System.out.println("Rule B");
end
RETE网络
有趣的是,此示例的RETE网络解析单个alpha节点内的OR运算符。
Drools内部使用了什么机制(我想是MVEL)来解决该节点,似乎实现了逻辑短路。我所做的测试表明,仅当使用少于30年的
Person
实例时才会引发预期的异常。最后说明
即使在单个模式中处理约束时,Drools似乎短路了,但是当规则包含多个模式时,情况也会有所不同。
根据我的测试,将使用短路启用算法来解决单个模式的所有约束。这主要取决于Rete网络中的alpha节点是按顺序评估的。
现在,在规则中处理多个模式时,无法在编译时预测评估顺序。规则中的每个模式都可以根据特定Rete网络查找特定情况的方式进行独立评估。
希望能帮助到你,
关于drools - 会在流口水LHS中“&&”或“,”“短路”吗?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/35953447/