(defrule rule
    (Customer (address ?address))
    (PO (customer ?customer))
(test (= 0 (str-compare ((?customer getAddress) getStreet) (? address getStreet))))
    =>
    (bind ?name (?customer getName))
    (bind ?addr (?address getStreet))
    (printout t ?addr ": customer: " ?name crlf)
)

Are there better, more elegant ways to accomplish the same?

Beauty is in the eye of the beholder, of course, but I'll offer one alternative that might work and then a little commentary.

I tried:

?po <-  (PO (customer ?customer))
?customer <-  (Customer (address ?address))
(test (= (((?po getCustomer) getAddress) getStreet) ((?customer getAddress) getStreet)))

But ?po and ?customer are facts (Jess.Fact) that have no getCustomer and getAddress methods.



(defrule match-street-in-purchase-to-other-customers-for-some-reason
        (PO (customer ?poCustomer))
        (Customer (OBJECT ?poCustomer)  (address ?poAddress))
        (Address (OBJECT ?poAddress) (street ?street))
(Customer (OBJECT ?customer&~?poCustomer) (address ? customerAddress)) ;This assumes we aren't matching the PO customer
        (Address (OBJECT ?customerAddress) (street ?street)
=>
;; do something here with something in purchase order unshown property (other than customer)?
)

It would also be possible to write methods on the classes that assist in this form of matching, to reduce the direct navigation through the object relationships. Something like a streetEq method, or more directly a getCustomerStreet() method on the PO class to avoid navigating in the pattern matches across the Customer.

There cam be real tension between object-oriented programming and rule-based programming. Encapsulation of objects and avoiding breaking Demeter's law can take a lot of the classic OPS5 rule look out of rule-programming. Adding properties (and accessors) to all the slots one might navigate through can add a burden to adding objects to the engine as the properties are shadowed, particularly if the properties are not easily computed/virtual.

- Mike


Reply via email to