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-boun...@lists.jboss.org [mailto:rules-users-boun...@lists.jboss.org] On Behalf Of Mark Proctor Sent: Tuesday, April 24, 2012 9:12 PM To: rules-users@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/resources/org/drools/games/pong/init.drl 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-boun...@lists.jboss.org > [mailto:rules-users-boun...@lists.jboss.org] On Behalf Of Welsh, Armand > Sent: Monday, April 23, 2012 3:22 PM > To: rules-users@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-boun...@lists.jboss.org > [mailto:rules-users-boun...@lists.jboss.org] On Behalf Of Christopher Dolan > Sent: Monday, April 23, 2012 1:01 PM > To: rules-users@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@lists.jboss.org > https://lists.jboss.org/mailman/listinfo/rules-users > > _______________________________________________ > rules-users mailing list > rules-users@lists.jboss.org > https://lists.jboss.org/mailman/listinfo/rules-users > > _______________________________________________ > rules-users mailing list > rules-users@lists.jboss.org > https://lists.jboss.org/mailman/listinfo/rules-users _______________________________________________ rules-users mailing list rules-users@lists.jboss.org https://lists.jboss.org/mailman/listinfo/rules-users _______________________________________________ rules-users mailing list rules-users@lists.jboss.org https://lists.jboss.org/mailman/listinfo/rules-users