'&&' 或 ',' "short-circuit" 会出现在 drools LHS 中吗?
will '&&' or ',' "short-circuit" in drools LHS?
我认为是,但我不是很确定。
例如:
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 方法将不会被评估?
谢谢!
我认为正确答案是
Person( age > 30 && calcIncome > 1000 )
如果 age <= 30
.
则不计算 calcIncome
删除了关于 "comma" 的虚假声明。
Drools 文档包含 && 和 , 运算符具有相同的语义。只有运算符优先级不同,逗号最低。
我自己做了一些测试,这是我发现的(至少在 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 运算。
同样,我使用逗号而不是符号得到了相同的结果。
DRL
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 年的 Person
个实例的测试证实了这一点:超过 30 年的实例抛出了 calcIncome()
.
的异常
规则 B
然后,我很好奇当我们使用 and 或 (||) 运算符而不是 and 时会发生什么。
DRL
rule "Rule B"
when
$p:Person(age > 30 || calcIncome() > 1000)
then
System.out.println("Rule B");
end
RETE 网络
有趣的是,此示例的 RETE 网络解析了单个 alpha 节点内的 OR 运算符。
无论 Drools 在内部使用什么机制(我猜是 MVEL)来解决这个节点,似乎都实现了逻辑短路。我所做的测试表明,仅当使用 Person
个小于 30 年的实例时才会抛出预期的异常。
最后的笔记
即使 Drools 在处理单个模式内的约束时似乎短路,但当规则包含多个模式时情况会有所不同。
根据我的测试,单个模式的所有约束都将使用启用短路的算法来解决。这主要依赖于 Rete 网络中的 alpha 节点是按顺序评估的。
现在,在处理规则中的多个模式时,无法在编译时预测求值顺序。规则中的每个模式都可以根据特定 Rete 网络如何查找特定案例进行独立评估。
希望对您有所帮助,
我认为是,但我不是很确定。 例如:
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 方法将不会被评估?
谢谢!
我认为正确答案是
Person( age > 30 && calcIncome > 1000 )
如果 age <= 30
.
calcIncome
删除了关于 "comma" 的虚假声明。
Drools 文档包含 && 和 , 运算符具有相同的语义。只有运算符优先级不同,逗号最低。
我自己做了一些测试,这是我发现的(至少在 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 运算。
同样,我使用逗号而不是符号得到了相同的结果。
DRL
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 年的 Person
个实例的测试证实了这一点:超过 30 年的实例抛出了 calcIncome()
.
规则 B
然后,我很好奇当我们使用 and 或 (||) 运算符而不是 and 时会发生什么。
DRL
rule "Rule B"
when
$p:Person(age > 30 || calcIncome() > 1000)
then
System.out.println("Rule B");
end
RETE 网络
有趣的是,此示例的 RETE 网络解析了单个 alpha 节点内的 OR 运算符。
无论 Drools 在内部使用什么机制(我猜是 MVEL)来解决这个节点,似乎都实现了逻辑短路。我所做的测试表明,仅当使用 Person
个小于 30 年的实例时才会抛出预期的异常。
最后的笔记
即使 Drools 在处理单个模式内的约束时似乎短路,但当规则包含多个模式时情况会有所不同。
根据我的测试,单个模式的所有约束都将使用启用短路的算法来解决。这主要依赖于 Rete 网络中的 alpha 节点是按顺序评估的。
现在,在处理规则中的多个模式时,无法在编译时预测求值顺序。规则中的每个模式都可以根据特定 Rete 网络如何查找特定案例进行独立评估。
希望对您有所帮助,