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] (.insert session p)) >> which would correspond roughly to >> for (Person p : allPersons) { session.insert(p); } >> Only that "person" is a map, not a class. >> Well, of course it is also an object and under the hood a class, a >> java.util.Map even - but I mean that unlike POJOs the key/value pairs >> are stored differently (fields in classes are also just key/value pairs). >> >> So, is there a way to insert maps (let it be java.util.HashMaps for >> example) and also to reason about them? I won't care if the syntax >> for that is complicated. As Clojure is a Lisp I would just write a >> little macro and have a very nice and readable syntax (probably a bit >> similar to the one of Jess or Lisa). >> Instead of looking at all instances of the type Person AND then have >> their age compared, I would look at all maps/structs which have a key >> :type with the value :person AND then compare the value of their :age >> key with a number, such as: >> (rule "example person rule, matching non-adults" >> :when (= :type :person) >> (< :age 18) >> :then >> (println "No service for minors.")) >> >> In Java terms it would mean that we insert several instances of >> java.util.HashMap, all having the k/v pairs for name, age and type. >> HashMap<String, Object> hm = new HashMap<String, Object>(); >> hm.put("name", someName); >> hm.put("age", someAge); >> hm.put("type", "person"); >> session.insert(hm); >> >> Is that in principle possible with Drools 5? >> >> >> Sunny greetings, >> André >> _______________________________________________ rules-users mailing list rules-users@lists.jboss.org https://lists.jboss.org/mailman/listinfo/rules-users