<br>&gt; So, in principle having Maps support in the LHS is not a big challenge?<br><br>No. Just requires developing a set of classes to work with maps. Being brief:<br><br>* Implement: MapObjectType extends ObjectType<br>
* Implement: MapReadAccessor and MapWriteAccessor<br>* Add support to them into the builders (i.e., the actual wiring of the new classes)<br>* Test everything... I probably forgot something, since there&#39;s been quite some time since I worked on this.<br>
<br>&gt; Could you please explain this in a bit more detail?<br>Lets call |A| the number of A facts in the working memory and |B| the number of B facts (i.e. cardinality). Lets call p(|A|,|B|) the number of partial matches a rule will create given the cardinality of A and B. Imagine your rule is:<br>
<br>when <br>   A()<br>   B()<br>then<br><br>This rule creates a join between A() and B() and the number of join attempts will be: p(|A|,|B|) = |A| * |B|<br><br>Now, if instead of representing A and B as different classes you use Maps with the type attribute as you was suggesting:<br>
<br>$a : Map()<br>$b : Map()<br>eval( ... )<br><br>The number of partial matches will be: p(|A|,|B|) = (|A|+|B|)! / (|A|+|B|-2)! <br><br>Draw the graph for these two functions and you will get the picture. If you have more than 2 patterns, situation gets worst and worst.<br>
<br>If instead of eval() you use some alpha constraints, things go down to the same level as using different classes:<br><br>$a : Map( this[&quot;type&quot;] == &quot;A&quot; )<br>
$b : Map( this[&quot;type&quot;] == &quot;B&quot; )<br>
<br>The above will result in the same p(|A|,|B|) = |A| * |B| partial matches.<br><br>[]s<br>Edson<br><br><br><div class="gmail_quote">2009/8/19 André Thieme <span dir="ltr">&lt;<a href="mailto:address.good.until.2009.dec.14@justmail.de">address.good.until.2009.dec.14@justmail.de</a>&gt;</span><br>
<blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;">Edson Tirelli schrieb:<br>
<div class="im">&gt;<br>
&gt;     I will skip the first half of your e-mail as I am not sure what were<br>
&gt; the reasons for your nit-picking. If my explanation was not helpful for<br>
&gt; the public it was intended to, you are welcome to explain yourself.<br>
<br>
</div>Oh, I did not intend it to sound like nit-picking. I only meant that<br>
with a specialized syntax one can make rules operating on Maps looking<br>
basically identical to the ones operating on POJOs.<br>
<div class="im"><br>
<br>
&gt;     Regarding the part that matters, i.e., adding the support to other<br>
&gt; fact types, Drools is prepared to support them in the LHS. Let me<br>
&gt; explain by example:<br>
&gt;<br>
&gt; when<br>
&gt;     $c : Customer( name == &quot;bob&quot; )<br>
&gt; then<br>
&gt;<br>
&gt;    For the reasoning algorithm, does not matter if Customer is a POJO,<br>
&gt; an XML document, a Map with the &quot;type&quot; attribute set to &quot;Customer&quot; as<br>
&gt; you mentioned, or whatever you can think. We use a set of interfaces<br>
&gt; that allows us to completely abstract that and we even supported 2<br>
&gt; different fact types as a proof of concept in the past.<br>
<br>
</div>That sounds good!<br>
So, in principle having Maps support in the LHS is not a big challenge?<br>
As I understand it, code inside an eval can not be cached and needs to<br>
get executed every time and results in less performant code.<br>
<div class="im"><br>
<br>
&gt;    The only reason we did not support multiple fact types yet for Drools<br>
&gt; is the RHS. Our reasoning is that does not make sense to abstract the<br>
&gt; LHS if you don&#39;t do the same for the RHS. So, for instance, using java<br>
&gt; dialect:<br>
&gt;<br>
&gt; when<br>
&gt;     $c : Person( name == &quot;bob&quot; )<br>
&gt; then<br>
&gt;     $c.setAge( 30 ) ;<br>
&gt; end<br>
&gt;<br>
&gt;     If we will support that rule, written as is, for POJOs, and we want<br>
&gt; to support Maps as facts, then our java parser needs to properly handle<br>
&gt; the consequence code as $c.put(&quot;age&quot;, 30). Same thing if Person was an<br>
&gt; XML document and so on.<br>
<br>
</div> From my perspective the RHS is not important at all for my lib and for<br>
Clojure users who like to work with Drools.<br>
For me mostly one thing is interesting: getting Map lookups out of eval,<br>
so they can profit from exactly the same caching and optimizations that<br>
exist for POJOs.<br>
<br>
The RHS will be fully written in Clojure, and all challenges that occur<br>
in it would have to be solved by myself.<br>
If you Drools Devs could make it possible to give support for Maps in<br>
the LHS, then most issues for Clojure users could be solved.<br>
<div class="im"><br>
<br>
&gt;<br>
&gt;     If you want to contribute to the project solving this problem, you<br>
&gt; are most welcome.<br>
<br>
</div>Unfortunately I have not enough Java knowledege and not time.<br>
But I would like to contribute indirectly, by writing a lib for Clojure<br>
users which will make Drools easily accessible to them. It would also<br>
provide other users of Drools with an alternative syntax, which gets<br>
compiled into the default rule language. (Not into mvel, as that seems<br>
to be interpreted and runs a bit slower.)<br>
<div class="im"><br>
<br>
&gt;     Regarding your rule rewrite, the way you propose is not feasible.<br>
&gt; Using multiple patterns of the same type without proper alpha<br>
&gt; constraints will lead to combinatorial explosion.<br>
<br>
</div>Could you please explain this in a bit more detail?<br>
If Maps as 1st class rule objects, shouldn&#39;t my example then be exactly<br>
the same as the one that you gave?<br>
<br>
Your example was:<br>
<div class="im"><br>
when<br>
   Customer( $custId : id )<br>
   DailyOrders( count[$custId] == 1 )<br>
</div>then ...<br>
<br>
<br>
My example was:<br>
<div class="im"><br>
rule &quot;Rule name&quot;<br>
   when<br>
     m1:clojure.lang.APersistentMap()<br>
     m2:clojure.lang.APersistentMap()<br>
     eval( m1.get(&quot;type&quot;) == &quot;Customer&quot; )<br>
     eval( m2.get(&quot;type&quot;) == &quot;DailyOrders&quot; &amp;&amp;<br>
          (m2.get(&quot;count&quot;)).get(m1.get(&quot;id&quot;)) == 1 )<br>
   then<br>
     ((clojure.lang.IFn)globalVarWithClojureCode.get(17)).call())<br>
end<br>
<br>
<br>
</div>And with direct Map support it could become something like:<br>
<br>
rule &quot;Rule name&quot;<br>
   MapDefaultKey &quot;type&quot;<br>
   Salience      2<br>
   when<br>
     &quot;Customer&quot;( $custId : &quot;id&quot; )<br>
     &quot;DailyOrders&quot;( get(&quot;count&quot;, $custId) == 1 )<br>
<div class="im">   then<br>
     ((clojure.lang.IFn)globalVarWithClojureCode.get(17)).call())<br>
end<br>
<br>
</div>Instead of the one could have syntactical sugar which may look<br>
unfamiliar: &quot;count&quot;[$custId]<br>
<br>
If the key is not a string but a float one would even have<br>
88.5[$custId] instead get(88, $custId).<br>
This is just a matter of taste, and users could have their DSLs anyway.<br>
<div><div></div><div class="h5"><br>
<br>
André<br>
--<br>
Lisp is not dead. It’s just the URL that has changed:<br>
<a href="http://clojure.org/" target="_blank">http://clojure.org/</a><br>
_______________________________________________<br>
rules-users mailing list<br>
<a href="mailto:rules-users@lists.jboss.org">rules-users@lists.jboss.org</a><br>
<a href="https://lists.jboss.org/mailman/listinfo/rules-users" target="_blank">https://lists.jboss.org/mailman/listinfo/rules-users</a><br>
</div></div></blockquote></div><br><br clear="all"><br>-- <br>  Edson Tirelli<br>  JBoss Drools Core Development<br>  JBoss by Red Hat @ <a href="http://www.jboss.com">www.jboss.com</a><br>