The fact that you can bind from a constant is good to know.
But if I can give my feeling, I don't think that this more readable nor more
maintainable.
To me, if you really want to factorize, using accumulate is better ...
Mark's rule has a relatively big an complex 'then' part that justify an
extreme conditions factorization, which is not really your case.
But this is just a matter of taste ...
Here is my ideal rule for this problem, using accumulate :
rule "household income"
when
$p1 : Person()
$additionnalIncome : Number() from accumulate (
Relation(person1 == $p1, type == "spouse", $p2income:
person2.getIncome()) ,
sum( $p2income )
)
then
insertLogical(new Income($p1.getIncome() + $additionnalIncome));
end
Note that this is working for multiple spouses too ...
But I have one question : will this work properly with insertLogical ?
----- Mail original -----
De: "Christopher Dolan" <christopher.dolan(a)avid.com>
À: "Rules Users List" <rules-users(a)lists.jboss.org>
Envoyé: Mercredi 25 Avril 2012 20:39:14
Objet: Re: [rules-users] Best practice for 0..1 relations
Aha, that makes sense! I didn't realize you could bind a variable from two different
branches of an "or". Following that pattern, my strawman rule becomes this:
rule "household income"
when
$p1 : Person()
((not Relation(person1 == $p1, type == "spouse") and $p2income : int
from 0) or
Relation(person1 == $p1, type == "spouse", $p2income:
person2.getIncome()))
then
insertLogical(new Income($p1.getIncome() + $p2income));
end
Thanks! That's a good compromise of readability and maintainability.
Chris
-----Original Message-----
From: rules-users-bounces(a)lists.jboss.org [mailto:rules-users-bounces@lists.jboss.org] On
Behalf Of Mark Proctor
Sent: Tuesday, April 24, 2012 9:12 PM
To: rules-users(a)lists.jboss.org
Subject: Re: [rules-users] Best practice for 0..1 relations
On 23/04/2012 21:31, Christopher Dolan wrote:
Sorry, I wasn't clear... In the example, it's the spouse
that's the optional fact. I want the rule to fire whether or not a spouse exists, but
the RHS computes the income differently if a spouse exists or not. If a spouse is
added/removed, I want the rule to re-fire and the income should be changed.
Take a
look at my Pong game and the "Create Ball" rule
https://github.com/droolsjbpm/drools/blob/master/drools-examples/src/main...
I create a ball with different dx directions depend on different states,
all from within one rule:
rule "Create Ball" when
not Ball()
( PointWin(player.id == PlayerId.PlayerOne ) and dx : Number() from 2 ) or
( PointWin(player.id == PlayerId.PlayerTwo ) and dx : Number() from -2 ) or
( not PointWin( ) and dx : Number() from -2 )
then
ball = new Ball( (pconf.tableWidth/2)-(pconf.ballWidth/2),
(pconf.tableHeight/2)-(pconf.ballWidth/2),
pconf.ballWidth);
ball.speed = pconf.ballStartingSpeed;
ball.dx = dx;
insert( ball );
end
Chris
-----Original Message-----
From: rules-users-bounces(a)lists.jboss.org [mailto:rules-users-bounces@lists.jboss.org] On
Behalf Of Welsh, Armand
Sent: Monday, April 23, 2012 3:22 PM
To: rules-users(a)lists.jboss.org
Subject: Re: [rules-users] Best practice for 0..1 relations
So, I assume the fact that is not needed in the LHS is Income.
By inserting Income into Working Memory, you are subjecting it to rete evaluation against
the current knowledge tree. I consider the cost of each operation. Insert is very
costly, and insertLogical even more costly.
I don't know anything about how your data model is built, but based on this very
simple example, I would think you would be better off with a Global like this:
Global Income income
Style 1: one rule for each scenario
rule "household income, single"
when
$p1 : Person()
not Relation(person1 == $p1, type == "spouse")
then
income = new Income($p1.getIncome());
end
rule "household income, married"
when
$p1 : Person()
Relation(person1 == $p1, type == "spouse", $p2: person2)
then
income = new Income($p1.getIncome() + $p2.getIncome());
end
Style 2: a single rule with a collection
rule "household income "
when
$p1 : Person()
$rels : List() from collect(Relation($p1 == person1, type ==
"spouse"))
then
income = new Income($p1.getIncome() + ($rels.size() == 0 ? 0 :
$rels.get(0).getPerson2().getIncome());
end
Then in code, you can get the Global value to determine what it got set to, if you need
outside of the Drools processing. All thread safety factors must be considered in a
multi-threaded environment. Global are not objects know to rete, and therefore, use of
them is very fast in the LHS. And the RHS is never aware of changes to Globals (drools
assumes them to be static values, that do not change) so care must be taken if using them
in the RHS of rules, which I would advise against doing except for special cases where you
know a change in the global variable won't be a problem (such as this simple scenario
where the global is not used in the RHS at all).
-----Original Message-----
From: rules-users-bounces(a)lists.jboss.org [mailto:rules-users-bounces@lists.jboss.org] On
Behalf Of Christopher Dolan
Sent: Monday, April 23, 2012 1:01 PM
To: rules-users(a)lists.jboss.org
Subject: [rules-users] Best practice for 0..1 relations
What's the best way to encode a fact that's needed in the RHS but is not
important in the LHS?
Consider a contrived example of computing total household income for single or married
persons. I can think of two ways to encode this rule, but I don't like either of
them:
Style 1: one rule for each scenario
rule "household income, single"
when
$p1 : Person()
not Relation(person1 == $p1, type == "spouse")
then
insertLogical(new Income($p1.getIncome()));
end
rule "household income, married"
when
$p1 : Person()
Relation(person1 == $p1, type == "spouse", $p2: person2)
then
insertLogical(new Income($p1.getIncome() + $p2.getIncome()));
end
Style 2: a single rule with a collection
rule "household income "
when
$p1 : Person()
$rels : List() from collect(Relation($p1 == person1, type ==
"spouse"))
then
insertLogical(new Income($p1.getIncome() + ($rels.size() == 0 ? 0 :
$rels.get(0).getPerson2().getIncome()));
end
(please ignore the bug that the income may get inserted twice because people are spouses
of each other)
Style 1 is more verbose, but more straightforward: it's how I think of the problem
intuitively. Style 2 is much more compact, and is more maintainable if I need to add more
predicates or a more complicated RHS. But the idea of needing a List when I know there
will be exactly 0 or 1 related facts just seems wrong.
I've searched for some LHS syntax that assigns a variable without participating in
boolean evaluation, but I've failed to find anything.
Chris
_______________________________________________
rules-users mailing list
rules-users(a)lists.jboss.org
https://lists.jboss.org/mailman/listinfo/rules-users
_______________________________________________
rules-users mailing list
rules-users(a)lists.jboss.org
https://lists.jboss.org/mailman/listinfo/rules-users
_______________________________________________
rules-users mailing list
rules-users(a)lists.jboss.org
https://lists.jboss.org/mailman/listinfo/rules-users
_______________________________________________
rules-users mailing list
rules-users(a)lists.jboss.org
https://lists.jboss.org/mailman/listinfo/rules-users
_______________________________________________
rules-users mailing list
rules-users(a)lists.jboss.org
https://lists.jboss.org/mailman/listinfo/rules-users