http://qs321.pair.com?node_id=362792


in reply to Checking lots of conditions...ORed and ANDed

If you're conditions are simple enough, turning your structure inside-out will help I think.

my $rules = { 'not in shift' => { allows => [ 'Register for shift', ], }, 'in shift' => { allows => [ 'Confirm in shift', 'Remove from shift', ], }, # 'current' => { # nothing seems to depend on current # }, 'past' => { disallows => [ 'Remove from shift', 'Register for shift', ], }, }; sub get_menu_items { my ($rules,@conditions) = @_; my %results; for my $cond ( @conditions ) { next unless exists $rules->{$cond}; # irrelevant condition for $item ( @{$rules->{$cond}->{allows}} ) { $results{$item}++; } for $item ( @{$rules->{$cond}->{disallows}} ) { delete $results{$item}; } } return keys %results; } my @conditions = ( ['in shift', 'past' ], ['in shift', 'current' ], ['not in shift', 'past' ], ['not in shift', 'current' ], ); for (@conditions) { my @result = get_menu_items($rules,@$_); print "Conditions: " . join(',',@$_) . "\n" . "Menu items: " . join(',',@result) . "\n\n"; }

And the results:

Conditions: in shift,past Menu items: Confirm in shift Conditions: in shift,current Menu items: Remove from shift,Confirm in shift Conditions: not in shift,past Menu items: Conditions: not in shift,current Menu items: Register for shift

This may just be a cheap application of others' suggestions to use boolean algebra and a state machine (or maybe not). I'm just a fan of code examples.

I DO think this is a very natural way for people to express rules in external config files.

--Solo
--
You said you wanted to be around when I made a mistake; well, this could be it, sweetheart.

Replies are listed 'Best First'.
Re^2: Checking lots of conditions...ORed and ANDed
by TVSET (Chaplain) on Jun 10, 2004 at 06:36 UTC
    It's a neat piece of code. ;) I still prefer my though due to two reasons:
    1. It is more obvious which conditions need to be satisfied for the menu to get displayed.
    2. Each menu caption is written only once. It is easier to maintain interface consistancy.

    Thank you for the idea anyway.

Re^2: Checking lots of conditions...ORed and ANDed
by Solo (Deacon) on Jun 15, 2004 at 14:32 UTC
    My above code has a nasty habit of allowing things it shouldn't depending on the order of the conditions. Assuming that 'disallow' rules trump 'allow' rules, here is a quick fix.

    sub get_menu_items { my ($rules,@conditions) = @_; my %results; for my $cond ( @conditions ) { next unless exists $rules->{$cond}; for $item ( @{$rules->{$cond}->{allows}} ) { $results{$item}++; } } for my $cond ( @conditions ) { next unless exists $rules->{$cond}; for $item ( @{$rules->{$cond}->{disallows}} ) { delete $results{$item}; } } return keys %results; }
    --Solo
    --
    You said you wanted to be around when I made a mistake; well, this could be it, sweetheart.