I came across a particular scenario when updating composed objects in Drools:
declare A
#propertyReactive
flag: Boolean
end
declare B
flag: Boolean
end
declare C
#propertyReactive
attrA: A
attrB: B
end
rule "Create A"
when
not A()
then
insert(new A());
System.out.println("OBJECT A CREATED");
end
rule "Create B"
when
not B()
then
insert(new B());
System.out.println("OBJECT B CREATED");
end
rule "Create C"
when
$A:A()
$B:B()
not C()
then
insert(new C($A,$B));
System.out.println("OBJECT C CREATED");
end
rule "Modify A"
when
$A:A(flag == false)
C()
then
modify($A) {setFlag(true)};
String $output = "Now A is " + $A.getFlag();
System.out.println($output);
end
rule "Print C when C is False"
when
C($A:attrA, attrA.flag == false, $B:attrB)
then
String $output = "A is " + $A.getFlag() + " and B is " + $B.getFlag();
System.out.println($output);
end
rule "Print C when C is True"
when
C($A:attrA, attrA.flag == true, $B:attrB)
then
String $output = "A is " + $A.getFlag() + " and B is " + $B.getFlag();
System.out.println($output);
end
rule "Print C when C is True 2"
when
C($A:attrA, $B:attrB)
A(this == $A, flag == true)
then
String $output = "2 A is " + $A.getFlag() + " and B is " + $B.getFlag();
System.out.println($output);
end
The output is:
OBJECT A CREATED
OBJECT B CREATED
OBJECT C CREATED
A is false and B is false
Now A is true
2 A is true and B is false
So I have the following questions:
Why is rule "Print C when C is True" not firing?
Why do I need to rewrite that rule as "Print C when C is True 2" to make it work?
Does anybody have an explanation for this?
It looks like Drools has an issue in working with accessors of nested classes...
Thank you very much.
Drools only reacts on changes performed to the objects used in your patterns and not to any nested object reference they may contain. And this is not entirely true either.
When you modify a fact in Drools (or any of its nested object references), you have the option to let Drools know about this modification or not. In your case, you are never notifying Drools about them. That is why your rules depend on the (not deterministic) evaluation order.
If you want to let Drools "know" about the modifications on a fact, then you must use the modify or update functions in the RHS of the rules where these modifications happen.
In your particular case, you have not only nested objects, but nested facts: A and C. Even if A is a fact, changes on A (even if properly notified to Drools) will never trigger the re-evaluation of a pattern like this:
C(attrA.flag == true)
The reason why is because the type of the pattern is C and not A. In these kind of scenarios, a rule written like your Print C when C is True 2 rule is a better approach.
Hope it helps,
Related
I am new to dart,
I was doing experiment with dart and suddenly got a problem,
I am using this logic to obtain it, correct me if i am wrong.
int a = 8;
int b = 7;
if (!(a <= b)){
print("A is Less");
}else{
print("B is Less");
}
Comments on your question recommend ">" which is correct, but I thought I could help you understand your sample if construct and why it prints the opposite of what is accurate.
Any conditions inside an if must evaluate to a single boolean: true or false. In your if you test "a is less than or equal to b", which will yield 'true' or 'false', then you invert that boolean value with the boolean "!" not operator. Boolean 'not' changes true to false, and false to true.
Given the values you set for a and b, your if statement therefore checks if a is less than or equal to b, which is "false", then inverts that "false" to "true" using "!" not, and therefore prints "A is Less", which is an incorrect statement.
FWIW, your logic will also print "B is less" when a = b;
I am using Drools rule engine and I was wondering if it was possible to define when a rule can be executed. For example:
If executing a rule A leads to executing 10 rules B1 to B10, is it possible to choose to execute only one of the Bi rules as a result of rule A??
An example would be :
rule "Rule A"
When
$var : Data(value>10)
then
doSmthg();
Event e = new Event();
insert(e);
end;
rule "Rule B"
When
$var : Data(range >100)
then
doSmthg();
Event e = new Event();
insert(e);
end;
rule "Rule C"
When
$e : Event()
then
doSmthg();
end;
Firing Rule A would lead to the execution of rule C.
Firing Rule B would lead to the execution of rule C.
Is there a way for me to make it so that rule C won't be fired even after rule A is executed? At the same time, firing B should still lead to the execution of rule C.
EDIT:
I have other rules that I need to be fired if Rule A is executed for example :
rule "Rule D"
When
$e : Event()
then
doSmthgElse();
end;
so in this case, I just want to disable Rule C from being fired without altering my other rules.
You are triggering subsequent rules by inserting data into working memory. If you don't want a rule to trigger a 'downstream' rule, don't insert the data. Or, alternatively, update the downstream rule to not trigger on the condition.
Consider these three rules, which are the same as yours but with syntax cleaned up and indentations fixed.
rule "Rule A"
when
Data( value>10 )
then
doSmthg();
insert(new Event());
end
rule "Rule B"
when
Data(range > 100)
then
doSmthg();
insert(new Event());
end
rule "Rule C"
when
$e : Event()
then
doSmthg();
end
Let's assume your input is Data( value = 100, range = 500 ). This is what will happen:
Rule A will hit because the condition value > 10 is met.
Rule B will hit because the condition range > 100 is met.
Rule C will hit twice because there are two instances of Event in working memory (one added by Rule A, one added by Rule B.)
Per your question, we don't want Rule C to fire because of Rule A in this condition. To do this, we need to change Rule A to not trigger Rule C. This is simple: remove the insert(new Event()) from the right hand side of Rule A.
rule "New Rule A"
when
Data( value > 10 )
then
doSmthg();
// No insert!
end
Rule B will still trigger because its condition (range > 100) is still met and it still inserts the Event instance into working memory.
Alternatively if what you're actually trying to do is have both A and B trigger C, but only to trigger C once, you can do that by inserting a semaphor into working memory to indicate that C is fired.
Here is an example:
rule "Rule A"
when
Data( value>10 )
then
doSmthg();
insert(new Event());
end
rule "Rule B"
when
Data(range > 100)
then
doSmthg();
insert(new Event());
end
rule "Rule C"
when
not( EventTriggered() )
$e : Event()
then
doSmthg();
insert( new EventTriggered() )
end
For the same input ( Data( value = 50, range = 500 ) ) this is what will happen:
Rule A will insert Event into working memory
Rule B will insert Event into working memory
Rule C will trigger from one of these Events. It will insert an instance of EventTriggered into working memory.
Rule C will not trigger a second time because the not() condition is not satisfied.
Using this setup, an input of Data( value = 5, range = 500 ) will still trigger Rule C via B:
Rule A will NOT fire (condition not met, value <= 10)
Rule B will fire, Event inserted into working memory
Rule C will fire.
And further, an input of Data( value = 50, range = 0) will also trigger Rule C via A:
Rule A will fire, Event inserted into working memory
Rule B will NOT fire (condition not met, range <= 100)
Rule C will fire.
Which solution you choose depends on what your actual requirements are.
If your requirement is that Rule A should never trigger Rule C, then the first solution (removing the insert statement) is the way to go.
If your requirement is that both Rule A and Rule B should trigger Rule C, but only once, then the second solution is the way to go.
I'm reading about Property based testing using Scala language. In this slide, they present this concept: For proving function a+b is true. we just only to prove those statements are true on random data:
a + b = b + a
a + 0 = a
a + 1 + 1 = a + 2
My question is: Which methodologies for checking that our test cases are enough, and can cover all cases on different data. For example on previous example, how can we sure that after our three properties run correctly, we can sure that our implementation is right.
First of all, I assume, you have a typo in #3, it's supposed to be + rather than *.
To answer your question, you most certainly can not be sure that your implementation is right if you prove these three properties. Consider this implementation for instance, that satisfies all three properties, but is definitely wrong:
def wrongPlus(a: Int, b: Int) = if(a < 3 || b <3) b a+b else 0
To definitively prove the (integer) addition, you need to have an independent implementation of next integer. Then, by definition:
1. a + 0 = a
2. a + next(b) = next(a + b)
If these properties hold for any a and b and some operation +, then + is indeed the addition.
Below is some simple example of the dsl. Let's say in WHEN block the true is "city == "NY"", is there a way to know, in the "then" block, which condition is true?
rule "First Promotion"
when
m : Promotion( city == "NY" || products == "SCHERP_S" || assignedProduct == "SCHERP_XL" )
then
**//Here I have to know what was true in WHEN block. For example city value is NY.**
end
thank you!
technically not since you used ||, but you could do multiple rules
rule "First Promotion_city"
when
m : Promotion( city == "NY")
then
end
rule "First Promotion_products"
when
m : Promotion( products == "SCHERP_S")
then
end
rule "First Promotion_assigned"
when
m : Promotion( assignedProduct == "SCHERP_XL")
then
end
Simply splitting the rule has the unpleasant side effect of requiring the multiplication of the condition (or using rule extension) and the multiplication of the consequences, with all disadvantages of code repetition.
A better solution is to use truth inference to create a suitable representation for a more to-the-point value.
Lets have a
class Reason {
Promotion promo;
String field;
String value;
Public( Promotion promo, String field, String value ){...}
//...
}
This can be used to register the reason for the disjunction using rules like this:
rule "First Promotion_city"
when
m : Promotion( $city: city == "NY" || "LA" )
then
insertLogical( new Reason( m, "city", $city ) );
end
I have added LA to show that multiple values can be handled with one rule.
The actual rule becomes
rule "First Promotion"
when
m : Promotion( )
r: Reason( promo == m )
then
//... access r for details
end
The disjunction may be true for more than one value, so you may have several Reason facts inserted. I can't advise on this since I don't know the "overall picture".
Clearly, the distinction on the RHS requires logic to decide what was true. But in the Q, there was no indication in which way one "has to know what was true". Accessing the original fact is, of course, the straightforward possibility. Having a value such as r.getField as a distinction right away, though, may be handy for selecting data from a map, etc. You get my drift.
local a = {}
function a:test1(value)
print(value)
end
local b = {}
function b:test2(v1, v2)
v2(100);
end
b:test2(_, a.test1)
Doesn't work. Value is nil. I could find a solution doing an encapsulation in an anonymous function
b:test2(variable, function(value) a:test1(value) end)
But I find it pretty bad mkay
What is the correct syntax ?
anotherObject:aFunction(variable, object.doStuff) is the correct syntax.
Using a colon : with a function is just syntactic sugar for a call or declaration with an implicit self parameter as the first argument. If you would like to follow the pattern you've shown in your example in a cleaner way, you could use a helper function.
local function bind(t, k)
return function(...) return t[k](t, ...) end
end
You then apply it like so.
anotherObject:aFunction(variable, bind(object, 'doStuff'))
Edit: I believe the solution to your problem will require binding at some level, without resorting to modifying the Lua interpreter or using a code translation step.
This is fundamentally because functions in Lua do not carry any information about their origin. I.e., tables do not inherently own the functions that they store.
For example, the following is perfectly legitimate Lua code.
function Circle:area() -- function Circle.area(self)
-- ...
end
-- Evaluate the function in the "area" slot with Square as the self parameter.
Circle.area(Square)
Of course, you could try a paradigm shift, but it may be too late for that if you're building an entire application based on the idea of functions being tied to the table that they have been indexed from, as you said.
Therefore, I propose the following crazy solution.
local mt = {}
function mt:__index(k)
local v = self._slots[k]
if v == nil then
-- Ascend the inheritance tree.
-- This has to be done with rawget all the way up,
-- otherwise inherited functions would be repeatedly bound.
local p = self
repeat
p = rawget(p, '_parent')
if not p then break end
v = p._slots[k]
until v
end
if type(v) == 'function' then
-- Return a self-bound version of the function.
return function(...) return v(self, ...) end
end
return v
end
function mt:__newindex(k, v)
self._slots[k] = v
end
--- Demo & Tests ---
local function Object(parent)
local o = setmetatable({_slots = {}}, mt)
if parent then rawset(o, '_parent', parent) end
return o
end
local o1 = Object()
local o2 = Object(o1)
assert(o1.abc == nil, 'o1.abc should be nil')
o1.abc = 3
assert(o1.abc == 3, 'o1.abc should be 3')
assert(o2.abc == 3, 'o2.abc should be 3, inherited from o1')
o2.abc = 7
assert(o2.abc == 7, 'o2.abc should be 7, overriding o1')
assert(o1.abc == 3, 'o1.abc should be 3, unaffected by o2 setter')
function o1:test(bar)
return self.abc + bar
end
assert(type(o1.test) == 'function', 'o1.test should be a function')
assert(type(o2.test) == 'function', 'o2.test should be a function, inherited from o1')
assert(o1.test(5) == 8, 'o1.test(5) should return 3 + 5 = 8')
assert(o2.test(11) == 18, 'o2.test(11) should return 7 + 11 = 18')
function o2:test2(fn)
return self.abc + fn(7)
end
assert(o2.test2(o1.test) == 17, 'o2.test2(o1.test) should return 7 + (3 + 7) = 17')
o2.test3 = o1._slots.test -- proper function copying
assert(o2.test3(11) == 18, 'o2.test3(5) should return 7 + 11 = 18')
o2.abc = nil
assert(o2.abc == 3, 'o2.abc should be 3 again, inherited from o1 after clearing')
o2.abc = false
assert(o2.abc == false, 'o2.abc should be false, __index needs to differentiate between nil and false')
This metatable will provide you with what you want, with inherited and bound functions to boot. You will just need to make sure that all of the tables that you want to follow this pattern also follow the method of object creation shown in the example code.
To explain, each table made in this way has any new assignment redirected into the _slots sub-table and any new retrieval checked up the _parent inheritance tree. If the type of the value is a function, then it returns a new closure with the original self that started the check bound to the function found.
Obviously, calling a function from one of these objects with the : colon syntax is going to be a silly idea, since it would evaluate to o.fn(o, o), and that is probably not what you want. Another caveat is that copying functions onto these objects, from these objects, will not work as expected. o1.newfn = o2.fn will put an o2 bound function into o1, which in turn will be re-bound to o1. The end result would be something like o2.fn(o2, o1). You will have to copy functions from the _slots table.
In conclusion: Even though this works, I would not personally recommend it in the long run, since it may be confusing to anyone used to how Lua works with tables, indexing, and functions, and there will be overhead. You might be able to do away with some it via memoizing the closures, but I'll leave that decision up to you. Good luck!
Object method declared with : needs object instance as the first parameter. It gets added automatically if you call it with :, but as you passed just a function pointer, you need to pass this as well. This means whenever you pass a function in some object somewhere, you also have to pass object instance. This works:
local a = {}
function a:test1(value)
print(value)
end
local b = {}
function b:test2(obj, v2)
v2(obj, 100); -- object instance is always the first param of a ":"-style func
end
b:test2(a, a.test1) -- passing object instance and a function
Building on #ryan-stein's neat bind() solution, in a module I've found this to be slightly more concise:
local m = {}
m.__index = m
m.word = 'bar'
function m:bind(fn)
return function(...) return self[fn](self, ...) end
end
function m:foo(fn)
print("Foo " .. self.word)
end
function m:start()
hs.timer.new(42, self:bind('foo'))
end
your code will be work. the reason Ryan has said.
I doubt that in the function anotherObject:aFunction(), you were using a wrong way to call the object.stuff.The correct way as this:
local a = {}
function a:test1()
print(1)
end
local b = {}
function b:test2(v1, v2)
v2();
end
b:test2(_, a.test1)