> So, in principle having Maps support in the LHS is not a big challenge?

No. Just requires developing a set of classes to work with maps. Being brief:

* Implement: MapObjectType extends ObjectType
* Implement: MapReadAccessor and MapWriteAccessor
* Add support to them into the builders (i.e., the actual wiring of the new classes)
* Test everything... I probably forgot something, since there's been quite some time since I worked on this.

> Could you please explain this in a bit more detail?
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:


This rule creates a join between A() and B() and the number of join attempts will be: p(|A|,|B|) = |A| * |B|

Now, if instead of representing A and B as different classes you use Maps with the type attribute as you was suggesting:

$a : Map()
$b : Map()
eval( ... )

The number of partial matches will be: p(|A|,|B|) = (|A|+|B|)! / (|A|+|B|-2)!

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.

If instead of eval() you use some alpha constraints, things go down to the same level as using different classes:

$a : Map( this["type"] == "A" )
$b : Map( this["type"] == "B" )

The above will result in the same p(|A|,|B|) = |A| * |B| partial matches.


2009/8/19 André Thieme <address.good.until.2009.dec.14@justmail.de>
Edson Tirelli schrieb:
>     I will skip the first half of your e-mail as I am not sure what were
> the reasons for your nit-picking. If my explanation was not helpful for
> the public it was intended to, you are welcome to explain yourself.

Oh, I did not intend it to sound like nit-picking. I only meant that
with a specialized syntax one can make rules operating on Maps looking
basically identical to the ones operating on POJOs.

>     Regarding the part that matters, i.e., adding the support to other
> fact types, Drools is prepared to support them in the LHS. Let me
> explain by example:
> when
>     $c : Customer( name == "bob" )
> then
>    For the reasoning algorithm, does not matter if Customer is a POJO,
> an XML document, a Map with the "type" attribute set to "Customer" as
> you mentioned, or whatever you can think. We use a set of interfaces
> that allows us to completely abstract that and we even supported 2
> different fact types as a proof of concept in the past.

That sounds good!
So, in principle having Maps support in the LHS is not a big challenge?
As I understand it, code inside an eval can not be cached and needs to
get executed every time and results in less performant code.

>    The only reason we did not support multiple fact types yet for Drools
> is the RHS. Our reasoning is that does not make sense to abstract the
> LHS if you don't do the same for the RHS. So, for instance, using java
> dialect:
> when
>     $c : Person( name == "bob" )
> then
>     $c.setAge( 30 ) ;
> end
>     If we will support that rule, written as is, for POJOs, and we want
> to support Maps as facts, then our java parser needs to properly handle
> the consequence code as $c.put("age", 30). Same thing if Person was an
> XML document and so on.

 From my perspective the RHS is not important at all for my lib and for
Clojure users who like to work with Drools.
For me mostly one thing is interesting: getting Map lookups out of eval,
so they can profit from exactly the same caching and optimizations that
exist for POJOs.

The RHS will be fully written in Clojure, and all challenges that occur
in it would have to be solved by myself.
If you Drools Devs could make it possible to give support for Maps in
the LHS, then most issues for Clojure users could be solved.

>     If you want to contribute to the project solving this problem, you
> are most welcome.

Unfortunately I have not enough Java knowledege and not time.
But I would like to contribute indirectly, by writing a lib for Clojure
users which will make Drools easily accessible to them. It would also
provide other users of Drools with an alternative syntax, which gets
compiled into the default rule language. (Not into mvel, as that seems
to be interpreted and runs a bit slower.)

>     Regarding your rule rewrite, the way you propose is not feasible.
> Using multiple patterns of the same type without proper alpha
> constraints will lead to combinatorial explosion.

Could you please explain this in a bit more detail?
If Maps as 1st class rule objects, shouldn't my example then be exactly
the same as the one that you gave?

Your example was:

  Customer( $custId : id )
  DailyOrders( count[$custId] == 1 )
then ...

My example was:

rule "Rule name"
    eval( m1.get("type") == "Customer" )
    eval( m2.get("type") == "DailyOrders" &&
         (m2.get("count")).get(m1.get("id")) == 1 )

And with direct Map support it could become something like:

rule "Rule name"
  MapDefaultKey "type"
  Salience      2
    "Customer"( $custId : "id" )
    "DailyOrders"( get("count", $custId) == 1 )

Instead of the one could have syntactical sugar which may look
unfamiliar: "count"[$custId]

If the key is not a string but a float one would even have
88.5[$custId] instead get(88, $custId).
This is just a matter of taste, and users could have their DSLs anyway.

Lisp is not dead. It’s just the URL that has changed:
rules-users mailing list

 Edson Tirelli
 JBoss Drools Core Development
 JBoss by Red Hat @ www.jboss.com