so - I have built a bit of a rules engine in python - but I'm fairly new to python... my engine is fairly nice to use - but adding a new rule is pretty ugly, and I'm wondering if there's a way to clean it up.
The key thing to remember is that rules have side-effects, rules can be combined with ands, ors, etc - and you only apply the side effects if the whole rule succeeded - ie the check if the rule succeeded can't be combined with perfoming the side effect.
So every rule ends up looking something like this:
def sample_rule():
def check( item ):
if item.doesnt_pass_some_condition(): return None
def action_to_perform():
item.set_some_value()
item.set_some_other_value()
return action_to_perform
return Rule(check)
which seems horribly ugly - but you don't seem to be able to do multiline lambdas or zero line lambas... I guess I'm looking for something like:
def sample_rule():
return Rule( lambda x: x.passes_condition(),
lambda x: {x.set_some_value(), x.set_some_other_value)}
but both the condition and the side effect could be multiple lines, and the side effect is often empty.
so is there a simpler pattern that i can apply that will apply to every case? (I really don't want to use the above pattern when I have exactly one line of condition and one line of side effect, and a completely different pattern in the other cases)
just out of interest, at the end you end up with something like
rule1 = sample_rule().andalso( other_rule_1().or(other_rule_2)).butnot( other_rule_3)
...
...
for thing_to_check in lots_of_things:
for rule in lots_of_rules:
if rule.apply_to( thing_to_check): break # take the first rule that applies