Re: [rules-users] Drools and Clojure
André Thieme wrote: Mark Proctor schrieb: André Thieme wrote: Mark Proctor schrieb: Map( this['c'] == 206 ) That should work, we do support MVEL syntax for maps and arrays - we just don't suppor method calls, yet. Hello Mark. I just tested it and it indeed works for me. Although as I understand it, this will be compiled into an expression using eval (or it will even be only interpreted). So, if that is true it can't bring any performance advantage. yes, no performance benefit. As this form of use is a "return value" really, it should be possible to index (if we assume that nest objects do not change). Although it's a fair bit of work to do this, but interesting work - if anyone wants to help out :) It would be fantastic if there was the same optimization support for Maps available as it exists for POJOs. Edson gave a great explanation on how things slow down for cross products. I thought about one thing: Could there could maybe be a new attribute, "immutable true" or something like that, which would signal that the rule writer promises the engine that only immutable objects are used? That way my lib could implicitly always set that attribute. It could certainly be done, lots of ways to cook this - from annotation on the pojo, type declarations and possibly some annotation on the rule or pattern itself. If you want to take a crack at this, you know where to find us :) http://www.jboss.org/drools/irc.html Mark The syntax is nothing I worry about. In Clojure, which is a Lisp, I have macros and can remove any obstacles in the syntax I like. It is trivial to develop new domain specific languages for rules. So, my rule syntax for Clojure will look very lispy, and each user is free to change and extend it. I will also allow the RHS to be written in Clojure code, no Java needed. Btw if you are doing "lispy" stuff: http://blog.athico.com/2008/02/drools-clips.html http://blog.athico.com/2008/06/drools-clips-progress.html Ah yes, very interesting. In principle it is very similar what I do. With Clojure there is a full featured Lisp on the JVM. What I do is adding some functions and macros, easy to use, which will do all the Drools managing and hide it from the user. It will be simple to add all kinds of syntaxes as soon I am done. You can have the Jess syntax. Just write a macro and expand it into mine. It will result in compiled rules code. So, in some days (when I have time) the project above will be finished ;-) see "Null-Safe Bean Navigation" http://mvel.codehaus.org/MVEL+2.0+Property+Navigation Ah of course, I forgot the null. And MVEL already has the check built in. I think I will also implicitly add it. And another interesting thing I noticed: to both rules I added the line global String s; and in the LHS's of both rules I removed the "c" and put s at its place. Then the first thing I did after creating a session was to (.setGlobal session "s" "c") The rule 1 accepted this change. I can use s instead of "c". But there is still the limitation that I can only insert Maps into the session which do have the String "c" as key. Otherwise: NPE. The rule 2 (mvel) however does not accept s as a placeholder. I get: Exception executing predicate this[s] == 206 [Thrown class org.drools.RuntimeDroolsException] Any ideas how to get rid of the NPE? We'll have to look into this, probably a bug. Edson confirmed that this is an MVEL problem. In a different thread KDR may have discovered another one. André ___ rules-users mailing list rules-users@lists.jboss.org https://lists.jboss.org/mailman/listinfo/rules-users
Re: [rules-users] Drools and Clojure
Mark Proctor schrieb: > > André Thieme wrote: >> Mark Proctor schrieb: >> >>> Map( this['c'] == 206 ) >>> >>> That should work, we do support MVEL syntax for maps and arrays - we >>> just don't suppor method calls, yet. >>> >> Hello Mark. I just tested it and it indeed works for me. >> Although as I understand it, this will be compiled into an expression >> using eval (or it will even be only interpreted). >> So, if that is true it can't bring any performance advantage. >> > yes, no performance benefit. As this form of use is a "return value" > really, it should be possible to index (if we assume that nest objects > do not change). Although it's a fair bit of work to do this, but > interesting work - if anyone wants to help out :) It would be fantastic if there was the same optimization support for Maps available as it exists for POJOs. Edson gave a great explanation on how things slow down for cross products. I thought about one thing: Could there could maybe be a new attribute, "immutable true" or something like that, which would signal that the rule writer promises the engine that only immutable objects are used? That way my lib could implicitly always set that attribute. >> The syntax is nothing I worry about. In Clojure, which is a Lisp, I have >> macros and can remove any obstacles in the syntax I like. It is trivial >> to develop new domain specific languages for rules. So, my rule syntax >> for Clojure will look very lispy, and each user is free to change and >> extend it. I will also allow the RHS to be written in Clojure code, no >> Java needed. >> > Btw if you are doing "lispy" stuff: > http://blog.athico.com/2008/02/drools-clips.html > http://blog.athico.com/2008/06/drools-clips-progress.html Ah yes, very interesting. In principle it is very similar what I do. With Clojure there is a full featured Lisp on the JVM. What I do is adding some functions and macros, easy to use, which will do all the Drools managing and hide it from the user. It will be simple to add all kinds of syntaxes as soon I am done. You can have the Jess syntax. Just write a macro and expand it into mine. It will result in compiled rules code. So, in some days (when I have time) the project above will be finished ;-) > see "Null-Safe Bean Navigation" > http://mvel.codehaus.org/MVEL+2.0+Property+Navigation Ah of course, I forgot the null. And MVEL already has the check built in. I think I will also implicitly add it. >> And another interesting thing I noticed: >> to both rules I added the line >> global String s; >> and in the LHS's of both rules I removed the "c" and put s at its place. >> Then the first thing I did after creating a session was to >> (.setGlobal session "s" "c") >> >> The rule 1 accepted this change. I can use s instead of "c". But there >> is still the limitation that I can only insert Maps into the session >> which do have the String "c" as key. Otherwise: NPE. >> The rule 2 (mvel) however does not accept s as a placeholder. I get: >> Exception executing predicate this[s] == 206 >> [Thrown class org.drools.RuntimeDroolsException] >> >> Any ideas how to get rid of the NPE? >> > We'll have to look into this, probably a bug. Edson confirmed that this is an MVEL problem. In a different thread KDR may have discovered another one. André -- Lisp is not dead. It’s just the URL that has changed: http://clojure.org/ ___ rules-users mailing list rules-users@lists.jboss.org https://lists.jboss.org/mailman/listinfo/rules-users
Re: [rules-users] Drools and Clojure
Well, you never know it performs until you try. :) See attached project. $ java -jar target/DroolsMapTest-1.0.jar eval.drl {bar=0} {foo=100} Time: 6607ms $ java -jar target/DroolsMapTest-1.0.jar mvel.drl {bar=0} {foo=100} Time: 13077ms So eval ended up being 2x as fast, at least for this micro benchmark. I guess the fact that the "this['foo']" expressions are not indexed, plus the fact that they're interpreted mvel, doubles up. Stick with the eval. --- On Thu, 8/13/09, André Thieme wrote: > From: André Thieme > Subject: Re: [rules-users] Drools and Clojure > To: "Rules Users List" > Date: Thursday, August 13, 2009, 6:29 PM > With what have you been wrong Greg? > I understood Marks reply in such a way that the mvel > dialect allows to > use Maps without eval. But this is just syntactic sugar. > When compiled > or interpreted (I don't know which of those Drools will do > with mvel > rules), this will get replaced with an eval under the > hood. > So, that means that still the optimizations can't be > applied. > Maybe the mvel rule is only interpreted, which would make > it even slower. > > For me it does not matter much which syntax will be my > target. > My Clojure lib will allow to write down rules in > s-expression > syntax, and it will compile them (compilation is also > available at > runtime) into any syntax Drools accepts. > Currently my target is the default syntax - that means I > will > produce strings that access Maps with eval. > > IF the mvel syntax will result in more performant code > because it > makes Drools handle it better without using eval under the > hood, then > sure, I can also compile into mvel syntax. > Although with that I still have the little problem to have > globals in > place of literals for Map lookups (see my other mail). > > > > Greg Barton schrieb: > > I was wrong. :). See Mark's later email. > > > > GreG > > > > On Aug 13, 2009, at 17:25, André Thieme > > > wrote: > > > > Greg Barton schrieb: > > There's no reason why a rete based system couldn't use > maps as first > > class objects, but Drools is heavily oriented towards > POJOS. Using > > eval in the way you have is pretty much the way to > go. > > > > Thanks for confirming that. > > For now I know that I am doing it right by using eval > and that this > > means that rules for typical Clojure objects will not > benefit from some > > of the optimizations Drools usually can apply. > > Maybe it will change in the future. > > > > > > As long as type information is accessible (both for > first class types > > and their members) you should be able to have the left > hand side of a > > rule (the conditions) be as it is now. > > > > I think that if Maps become 1st class objects there > could be a different > > Syntax, without using eval. > > > > > > If you lobby the devs hard enough and get others on > your side you may > > be able to convince them to go in that direction, but > I doubt it > > would be possible before version 6 or so, if that > early. (And I'm > > not even sure it's possible.) > > > > At this point it is mostly interesting for me to get > Drools working with > > Clojure together and concentrate on correctness. The > goal is that users > > of my lib can use do all typical things people do with > Drools without > > writing Java code. Everything, including the rules, > would be written in > > Clojure. > > But of course it would be very interesting if the devs > could indeed have > > Clojure in mind. I don't know how reusable the > existing code is, for > > using Maps without the need for eval and with having > the respective > > performance advantages. > > I understand that the looup of the value for a given > key can not be > > optimized away. On my hardware get() is limited to > "only" 1000 calls > > per msec and core. Reading a field from a POJO is > faster. > > If I understand it correctly then the "problem" with > eval is that it > > needs to be executed each time, and no clever caching > can be done. > > So, eliminating that by having Maps being 1st class is > what sounds > > interesting. > > When I refer to Maps and Clojure, then I talk about > Maps having only > > very few key/value pairs, just like POJOs, and being > immutable. > > This immutability may even be very helpful for > optimization. It is > > guaranteed that a given object will never change. > > > > I hope the devs will find it okay if I make some > concrete suggestions > > in the coming weeks. > > > > > > Sunny greetings, > > André > > > -- > Lisp is not dead. It’s just the URL that has changed: > http://clojure.org/ > ___ > rules-users mailing list > rules-users@lists.jboss.org > https://lists.jboss.org/mailman/listinfo/rules-users > DroolsMap.tar.gz Description: GNU Zip compressed data ___ rules-users mailing list rules-users@lists.jboss.org https://lists.jboss.org/mailman/listinfo/rules-users
Re: [rules-users] Drools and Clojure
André Thieme wrote: Mark Proctor schrieb: Map( this['c'] == 206 ) That should work, we do support MVEL syntax for maps and arrays - we just don't suppor method calls, yet. Hello Mark. I just tested it and it indeed works for me. Although as I understand it, this will be compiled into an expression using eval (or it will even be only interpreted). So, if that is true it can't bring any performance advantage. yes, no performance benefit. As this form of use is a "return value" really, it should be possible to index (if we assume that nest objects do not change). Although it's a fair bit of work to do this, but interesting work - if anyone wants to help out :) The syntax is nothing I worry about. In Clojure, which is a Lisp, I have macros and can remove any obstacles in the syntax I like. It is trivial to develop new domain specific languages for rules. So, my rule syntax for Clojure will look very lispy, and each user is free to change and extend it. I will also allow the RHS to be written in Clojure code, no Java needed. Btw if you are doing "lispy" stuff: http://blog.athico.com/2008/02/drools-clips.html http://blog.athico.com/2008/06/drools-clips-progress.html But back to your example: I noticed something very interesting: when I use the MVEL dialect for the Map lookup, then I get no NPE anymore when I check in a Map which does *not* have the key I test for. So, now I have two versions of my rule: package droolsandclojure; import java.util.Map; rule "Clojure test 1" when m:Map() eval((Integer)m.get("c") == 206) then System.out.println("Match: " + m); end and package droolsandclojure; import java.util.Map; rule "Clojure MVEL test 2" dialect "mvel" when m:Map( this["c"] == 206 ) then System.out.println("Match: " + m); end Only one of these two rules is used, not both at the same time. When I use rule 1 then I can not insert Maps into my session which do not have a key "c". If I try it and run my code I get a NPE. When I use rule 2, the MVEL version, this is different. Now I can insert any Maps and will not get an exception. The rule will simply just not execute the RHS. How can rule 1 be changed so that it will not put a constraint on the objects which are allowed to go into the session without throwing a NPE? see "Null-Safe Bean Navigation" http://mvel.codehaus.org/MVEL+2.0+Property+Navigation And another interesting thing I noticed: to both rules I added the line global String s; and in the LHS's of both rules I removed the "c" and put s at its place. Then the first thing I did after creating a session was to (.setGlobal session "s" "c") The rule 1 accepted this change. I can use s instead of "c". But there is still the limitation that I can only insert Maps into the session which do have the String "c" as key. Otherwise: NPE. The rule 2 (mvel) however does not accept s as a placeholder. I get: Exception executing predicate this[s] == 206 [Thrown class org.drools.RuntimeDroolsException] Any ideas how to get rid of the NPE? We'll have to look into this, probably a bug. Mark ___ rules-users mailing list rules-users@lists.jboss.org https://lists.jboss.org/mailman/listinfo/rules-users
Re: [rules-users] Drools and Clojure
With what have you been wrong Greg? I understood Marks reply in such a way that the mvel dialect allows to use Maps without eval. But this is just syntactic sugar. When compiled or interpreted (I don't know which of those Drools will do with mvel rules), this will get replaced with an eval under the hood. So, that means that still the optimizations can't be applied. Maybe the mvel rule is only interpreted, which would make it even slower. For me it does not matter much which syntax will be my target. My Clojure lib will allow to write down rules in s-expression syntax, and it will compile them (compilation is also available at runtime) into any syntax Drools accepts. Currently my target is the default syntax - that means I will produce strings that access Maps with eval. IF the mvel syntax will result in more performant code because it makes Drools handle it better without using eval under the hood, then sure, I can also compile into mvel syntax. Although with that I still have the little problem to have globals in place of literals for Map lookups (see my other mail). Greg Barton schrieb: > I was wrong. :). See Mark's later email. > > GreG > > On Aug 13, 2009, at 17:25, André Thieme > wrote: > > Greg Barton schrieb: > There's no reason why a rete based system couldn't use maps as first > class objects, but Drools is heavily oriented towards POJOS. Using > eval in the way you have is pretty much the way to go. > > Thanks for confirming that. > For now I know that I am doing it right by using eval and that this > means that rules for typical Clojure objects will not benefit from some > of the optimizations Drools usually can apply. > Maybe it will change in the future. > > > As long as type information is accessible (both for first class types > and their members) you should be able to have the left hand side of a > rule (the conditions) be as it is now. > > I think that if Maps become 1st class objects there could be a different > Syntax, without using eval. > > > If you lobby the devs hard enough and get others on your side you may > be able to convince them to go in that direction, but I doubt it > would be possible before version 6 or so, if that early. (And I'm > not even sure it's possible.) > > At this point it is mostly interesting for me to get Drools working with > Clojure together and concentrate on correctness. The goal is that users > of my lib can use do all typical things people do with Drools without > writing Java code. Everything, including the rules, would be written in > Clojure. > But of course it would be very interesting if the devs could indeed have > Clojure in mind. I don't know how reusable the existing code is, for > using Maps without the need for eval and with having the respective > performance advantages. > I understand that the looup of the value for a given key can not be > optimized away. On my hardware get() is limited to "only" 1000 calls > per msec and core. Reading a field from a POJO is faster. > If I understand it correctly then the "problem" with eval is that it > needs to be executed each time, and no clever caching can be done. > So, eliminating that by having Maps being 1st class is what sounds > interesting. > When I refer to Maps and Clojure, then I talk about Maps having only > very few key/value pairs, just like POJOs, and being immutable. > This immutability may even be very helpful for optimization. It is > guaranteed that a given object will never change. > > I hope the devs will find it okay if I make some concrete suggestions > in the coming weeks. > > > Sunny greetings, > André -- Lisp is not dead. It’s just the URL that has changed: http://clojure.org/ ___ rules-users mailing list rules-users@lists.jboss.org https://lists.jboss.org/mailman/listinfo/rules-users
Re: [rules-users] Drools and Clojure
Mark Proctor schrieb: > Map( this['c'] == 206 ) > > That should work, we do support MVEL syntax for maps and arrays - we > just don't suppor method calls, yet. Hello Mark. I just tested it and it indeed works for me. Although as I understand it, this will be compiled into an expression using eval (or it will even be only interpreted). So, if that is true it can't bring any performance advantage. The syntax is nothing I worry about. In Clojure, which is a Lisp, I have macros and can remove any obstacles in the syntax I like. It is trivial to develop new domain specific languages for rules. So, my rule syntax for Clojure will look very lispy, and each user is free to change and extend it. I will also allow the RHS to be written in Clojure code, no Java needed. But back to your example: I noticed something very interesting: when I use the MVEL dialect for the Map lookup, then I get no NPE anymore when I check in a Map which does *not* have the key I test for. So, now I have two versions of my rule: package droolsandclojure; import java.util.Map; rule "Clojure test 1" when m:Map() eval((Integer)m.get("c") == 206) then System.out.println("Match: " + m); end and package droolsandclojure; import java.util.Map; rule "Clojure MVEL test 2" dialect "mvel" when m:Map( this["c"] == 206 ) then System.out.println("Match: " + m); end Only one of these two rules is used, not both at the same time. When I use rule 1 then I can not insert Maps into my session which do not have a key "c". If I try it and run my code I get a NPE. When I use rule 2, the MVEL version, this is different. Now I can insert any Maps and will not get an exception. The rule will simply just not execute the RHS. How can rule 1 be changed so that it will not put a constraint on the objects which are allowed to go into the session without throwing a NPE? And another interesting thing I noticed: to both rules I added the line global String s; and in the LHS's of both rules I removed the "c" and put s at its place. Then the first thing I did after creating a session was to (.setGlobal session "s" "c") The rule 1 accepted this change. I can use s instead of "c". But there is still the limitation that I can only insert Maps into the session which do have the String "c" as key. Otherwise: NPE. The rule 2 (mvel) however does not accept s as a placeholder. I get: Exception executing predicate this[s] == 206 [Thrown class org.drools.RuntimeDroolsException] Any ideas how to get rid of the NPE? -- Lisp is not dead. It’s just the URL that has changed: http://clojure.org/ ___ rules-users mailing list rules-users@lists.jboss.org https://lists.jboss.org/mailman/listinfo/rules-users
Re: [rules-users] Drools and Clojure
I was wrong. :). See Mark's later email. GreG On Aug 13, 2009, at 17:25, André Thieme wrote: Greg Barton schrieb: There's no reason why a rete based system couldn't use maps as first class objects, but Drools is heavily oriented towards POJOS. Using eval in the way you have is pretty much the way to go. Thanks for confirming that. For now I know that I am doing it right by using eval and that this means that rules for typical Clojure objects will not benefit from some of the optimizations Drools usually can apply. Maybe it will change in the future. As long as type information is accessible (both for first class types and their members) you should be able to have the left hand side of a rule (the conditions) be as it is now. I think that if Maps become 1st class objects there could be a different Syntax, without using eval. If you lobby the devs hard enough and get others on your side you may be able to convince them to go in that direction, but I doubt it would be possible before version 6 or so, if that early. (And I'm not even sure it's possible.) At this point it is mostly interesting for me to get Drools working with Clojure together and concentrate on correctness. The goal is that users of my lib can use do all typical things people do with Drools without writing Java code. Everything, including the rules, would be written in Clojure. But of course it would be very interesting if the devs could indeed have Clojure in mind. I don't know how reusable the existing code is, for using Maps without the need for eval and with having the respective performance advantages. I understand that the looup of the value for a given key can not be optimized away. On my hardware get() is limited to "only" 1000 calls per msec and core. Reading a field from a POJO is faster. If I understand it correctly then the "problem" with eval is that it needs to be executed each time, and no clever caching can be done. So, eliminating that by having Maps being 1st class is what sounds interesting. When I refer to Maps and Clojure, then I talk about Maps having only very few key/value pairs, just like POJOs, and being immutable. This immutability may even be very helpful for optimization. It is guaranteed that a given object will never change. I hope the devs will find it okay if I make some concrete suggestions in the coming weeks. Sunny greetings, André -- Lisp is not dead. It’s just the URL that has changed: http://clojure.org/ ___ 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
Re: [rules-users] Drools and Clojure
Greg Barton schrieb: > There's no reason why a rete based system couldn't use maps as first > class objects, but Drools is heavily oriented towards POJOS. Using > eval in the way you have is pretty much the way to go. Thanks for confirming that. For now I know that I am doing it right by using eval and that this means that rules for typical Clojure objects will not benefit from some of the optimizations Drools usually can apply. Maybe it will change in the future. > As long as type information is accessible (both for first class types > and their members) you should be able to have the left hand side of a > rule (the conditions) be as it is now. I think that if Maps become 1st class objects there could be a different Syntax, without using eval. > If you lobby the devs hard enough and get others on your side you may > be able to convince them to go in that direction, but I doubt it > would be possible before version 6 or so, if that early. (And I'm > not even sure it's possible.) At this point it is mostly interesting for me to get Drools working with Clojure together and concentrate on correctness. The goal is that users of my lib can use do all typical things people do with Drools without writing Java code. Everything, including the rules, would be written in Clojure. But of course it would be very interesting if the devs could indeed have Clojure in mind. I don't know how reusable the existing code is, for using Maps without the need for eval and with having the respective performance advantages. I understand that the looup of the value for a given key can not be optimized away. On my hardware get() is limited to "only" 1000 calls per msec and core. Reading a field from a POJO is faster. If I understand it correctly then the "problem" with eval is that it needs to be executed each time, and no clever caching can be done. So, eliminating that by having Maps being 1st class is what sounds interesting. When I refer to Maps and Clojure, then I talk about Maps having only very few key/value pairs, just like POJOs, and being immutable. This immutability may even be very helpful for optimization. It is guaranteed that a given object will never change. I hope the devs will find it okay if I make some concrete suggestions in the coming weeks. Sunny greetings, André -- Lisp is not dead. It’s just the URL that has changed: http://clojure.org/ ___ rules-users mailing list rules-users@lists.jboss.org https://lists.jboss.org/mailman/listinfo/rules-users
Re: [rules-users] Drools and Clojure
Golly, that's just too easy. :P --- On Tue, 8/11/09, Mark Proctor wrote: > From: Mark Proctor > Subject: Re: [rules-users] Drools and Clojure > To: "Rules Users List" > Date: Tuesday, August 11, 2009, 11:09 PM > Map( this['c'] == 206 ) > > That should work, we do support MVEL syntax for maps and > arrays - we > just don't suppor method calls, yet. ___ rules-users mailing list rules-users@lists.jboss.org https://lists.jboss.org/mailman/listinfo/rules-users
Re: [rules-users] Drools and Clojure
Map( this['c'] == 206 ) That should work, we do support MVEL syntax for maps and arrays - we just don't suppor method calls, yet. Mark André Thieme wrote: > My previous mail did not really have any resonance, which is probably > due to the fact that I put the word "Clojure" into the subject. Some of > you may not know that Clojure is a programming language which compiles > to Java byte code and which can use all Java classes and which can > itself also produce classes which are then usable in Java. > I hope this time some people will answer :-) > I would like to see some comments about the eval+Maps issue and a tip > how I can have rules which are not constraints at the same time about > what can be inserted into a session. > > > Currently I am writing a lib which will make Drools usable from within > the Clojure programming language. That is good for both, Drools and > Clojure. That way Drools gets more users and more Clojure users can use > that powerful system. > > At the end of this mail you will find my original one that I sent some > days ago which got no answer. By now I found out the answer myself. > My question was if I can write rules which will fire when some specific > key/value pairs are set in a HashMap. And yes, I was able to do this via > eval. > > Is there really no other way than using eval? > The disadvantage seems to be that Drools can not do optimizations over > evals, but needs to execute that code each time. > In Clojure it is typical to use Maps instead of POJOs. That would mean > that Clojure users either have to do non-idiomatic programming, or > accept that their rules will be slower. > Although in principle maps and class instances are equivalent. POJOs are > also maps. They map a key, the field of the class, to a value. POJOs > have one implicit field, which is their type. > We could have a > class Person { >String name; >int age; >... > } > or a Map with just three fields: name, age and type. > In the type slot we could store the string "Person". > Clojure Maps are immutable which should allow even more optimizations > than we can have in Drools from POJOs. > Anyway, here is a rule that I currently use: > > package droolsandclojure; > import clojure.lang.APersistentMap; > > rule "Clojure test 1" > when >m:APersistentMap() >eval((Integer)m.get("c") == 206) > then >System.out.println("Match: " + m); > end > > and in my Clojure program I create a stateful session object and then > (.insert session {"a" 1, "b" 2, "c" 3}) > (.insert session {"a" 1, "b" 2, "c" 206}) > which inserts two maps into the session object. > When I then (.fireAllRules session) then it prints out > Match: {"a" 1, "b" 2, "c" 206} > as expected. > One thing is strange though: I can not insert Maps which don't have a > key "c" - I get a NullPointerException. > It seems that I set a constraint of which things can go into a session > instead of having a rule which fires only for those Maps that come with > the right key/value pairs. Btw, this also happens when I use a > java.util.HashMap instead of the Clojure one. > > The rule then looks like: > package droolsandclojure; > import java.util.Map; > > rule "Clojure test 2" > when >m:Map() >eval((Integer)m.get("c") == 206) > then >System.out.println("Match: " + m); > end > > And I do > (let [map (new java.util.HashMap)] >(.put map "a" 10) >(.put map "b" 20) >(.put map "c" 206) >... >(.insert session map) >...) > > which then prints: > Match: {b=20, c=206, a=10} > But if I don't (.put map "c" 206) but instead (.put map "d" 206) then I > get the NPE. > > Here my earlier original mail which you can safely ignore. > > > Greetings, > André > > > > > André Thieme schrieb: > >> Hello group! >> >> I am a Clojure user and would like to look into using Drools with it. >> From Clojure I can use all Java classes and call all methods. So, >> instantiating a KnowledgeBase, KnowledgePackages or a KBFactory is no >> problem, and calling the respective methods, to get the system started, >> or insert facts into a session, dispose it and fireAllRules is also >> fine. >> >> It is just that in Clojure one typically does not use POJOs. >> The most typical data structures used are: hashmaps, vectors, structs, >> lists, structuremaps and sets (in no particular order). >> Those are persistent and "concurrency ready" Clojure DSs, and btw, also >> usable from Java directly. >> >> Now the basic Drools examples I saw all work with POJOs. >> They were mostly comparisons of native typed fields in a class. >> I however would be interested to compare different qualities of key/ >> value pairs in a hashmap, or compare structs with each other. >> Comparing structuremaps is maybe what comes closest to the POJO examples. >> For example, we may have a struct (defstruct person :name :age :type) >> and store it's instances in a vector. And we would also insert it into >> our Drools session object: >> (doseq [p all-persons] (.inser
Re: [rules-users] Drools and Clojure
There's no reason why a rete based system couldn't use maps as first class objects, but Drools is heavily oriented towards POJOS. Using eval in the way you have is pretty much the way to go. That being said, a possible direction for Drools might be the way the object-relational mapper Hibernate handles things: tuplizers. When you create a Hibernate session you can specify how you want it to instantiate the data mapped in the database. There are three built in tuplizers: Dom4jEntityTuplizer, DynamicMapEntityTuplizer, and PojoEntityTuplizer. (And you can create custom ones.) As long as type information is accessible (both for first class types and their members) you should be able to have the left hand side of a rule (the conditions) be as it is now. The right hand side is another story entirely, as Drools does no processing on it whatsoever. Creating new working memory objects could not be generic, and neither would modification of existing objects. If you did want to make it generic, you would lose the full power of java by handing working memory object creation and modification over to Drools. In my experience when systems try to take on that responsibility they don't do it as well, or as flexibly, as java does. If you lobby the devs hard enough and get others on your side you may be able to convince them to go in that direction, but I doubt it would be possible before version 6 or so, if that early. (And I'm not even sure it's possible.) --- On Tue, 8/11/09, André Thieme wrote: > From: André Thieme > Subject: [rules-users] Drools and Clojure > To: "Rules Users List" > Date: Tuesday, August 11, 2009, 5:01 PM > My previous mail did not really have > any resonance, which is probably > due to the fact that I put the word "Clojure" into the > subject. Some of > you may not know that Clojure is a programming language > which compiles > to Java byte code and which can use all Java classes and > which can > itself also produce classes which are then usable in Java. > I hope this time some people will answer :-) > I would like to see some comments about the eval+Maps issue > and a tip > how I can have rules which are not constraints at the same > time about > what can be inserted into a session. > > > Currently I am writing a lib which will make Drools usable > from within > the Clojure programming language. That is good for both, > Drools and > Clojure. That way Drools gets more users and more Clojure > users can use > that powerful system. > > At the end of this mail you will find my original one that > I sent some > days ago which got no answer. By now I found out the answer > myself. > My question was if I can write rules which will fire when > some specific > key/value pairs are set in a HashMap. And yes, I was able > to do this via > eval. > > Is there really no other way than using eval? > The disadvantage seems to be that Drools can not do > optimizations over > evals, but needs to execute that code each time. > In Clojure it is typical to use Maps instead of POJOs. That > would mean > that Clojure users either have to do non-idiomatic > programming, or > accept that their rules will be slower. > Although in principle maps and class instances are > equivalent. POJOs are > also maps. They map a key, the field of the class, to a > value. POJOs > have one implicit field, which is their type. > We could have a > class Person { > String name; > int age; > ... > } > or a Map with just three fields: name, age and type. > In the type slot we could store the string "Person". > Clojure Maps are immutable which should allow even more > optimizations > than we can have in Drools from POJOs. > Anyway, here is a rule that I currently use: > > package droolsandclojure; > import clojure.lang.APersistentMap; > > rule "Clojure test 1" > when > m:APersistentMap() > eval((Integer)m.get("c") == 206) > then > System.out.println("Match: " + m); > end > > and in my Clojure program I create a stateful session > object and then > (.insert session {"a" 1, "b" 2, "c" 3}) > (.insert session {"a" 1, "b" 2, "c" 206}) > which inserts two maps into the session object. > When I then (.fireAllRules session) then it prints out > Match: {"a" 1, "b" 2, "c" 206} > as expected. > One thing is strange though: I can not insert Maps which > don't have a > key "c" - I get a NullPointerException. > It seems that I set a constraint of which things can go > into a session > instead of having a rule which fires only for those Maps > that come with > the right key/value pairs. Btw, this also happens when I > use a > java.util.HashMap instead of the Clojure one. > > The rule then looks like: > package droolsandclojure; > import java.util.Map; > > rule "Clojure test 2" > when > m:Map() > eval((Integer)m.get("c") == 206) > then > System.out.println("Match: " + m); > end > > And I do > (let [map (new java.util.HashMap)] > (.put map "a" 10) > (.put map "b" 20) > (.put