Attributes of contained objects may be made attributes of the containing object by adding getters to the latter that propagate to the contained object. I think that the extra effort for implementing these in the (shadow) fact classes pays back when writing rules that require such accesses.
Of course, going down three (pr more) levels as in PO.getCustomer().getAddress().getStreet() might bloat these classes considerably or even intolerably. In such cases, consider inserting a contained top level object as a fact of its own. -W On Sat, Sep 5, 2009 at 4:24 AM, Michael Smith <[email protected]>wrote: > > (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 > > >
