我认为是,但我不太确定。 例如:
class Person {
int age;
int salary;
int bonus;
//getter and setter
public int calcIncome () {
return salary + bonus;
}
}
DRL:
when
$p:Person(age > 30, calcIncome() > 1000)
then
...
等于:
if (person.getAge() > 30 && person.calcIncome() > 1000) {
...
}
所以当人的年龄不大于30时,不会评估calcIncome方法吗?
谢谢!
答案 0 :(得分:3)
我自己做了一些测试,这是我发现的(至少在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()
中抛出异常。
此规则使用'&&'指示Person
模式上的2个约束之间的AND运算。
同样,我使用逗号而不是&符号得到了相同的结果。
rule "Rule A"
when
$p:Person(age > 30 && calcIncome() > 1000)
then
System.out.println("Rule A");
end
先例规则的Rete网络如下所示:
在上图中,我们可以看到2个不同的alpha节点(黄色)。因为alpha节点是按顺序计算的,所以第二个节点只会被评估,在这种情况下,如果我们评估的Person
已超过30年。
使用超过30年的Person
个实例进行的测试证实了这一点:超过30年的实例抛出了calcIncome()
的异常。
然后,我很好奇当我们使用和/或(||)运算符而不是和。时发生的事情。
rule "Rule B"
when
$p:Person(age > 30 || calcIncome() > 1000)
then
System.out.println("Rule B");
end
有趣的是,此示例的RETE网络解析了单个alpha节点内的OR运算符。
Drools在内部使用的任何机制(我猜是MVEL)来解析这个节点似乎都实现了逻辑短路。我所做的测试表明,只有在使用少于30年的Person
个实例时,才会抛出预期的异常。
即使Drools在处理单个Pattern中的约束时似乎短路,但当规则包含多个模式时,情况会有所不同。
根据我的测试,使用启用短路的算法可以解决单个模式的所有约束。这主要依赖于Rete网络中的alpha节点按顺序进行评估的事实。
现在,在处理规则中的多个模式时,无法在编译时预测评估顺序。可以根据特定Rete网络查找特定情况的方式独立评估规则中的每个模式。
希望它有所帮助,
答案 1 :(得分:1)
我认为正确答案是
Person( age > 30 && calcIncome > 1000 )
如果calcIncome
,则不会评估age <= 30
。
删除了虚假声明“逗号”。
Drools文档包含&amp;&amp;并且,运算符具有相同的语义。运算符优先级只有差异,逗号最低。