You're absolutely right.  In my case though, I wanted a general
purpose user function that could act on all of the facts which
contributed to the firing of the rule.  I want to be able to create an
audit trail of why various rules fired.  I didn't want the rule writer
to have to worry about passing the appropriate parameters.
 
- Alan

________________________________

From: [EMAIL PROTECTED] [mailto:[EMAIL PROTECTED]
On Behalf Of Robert Kirby
Sent: Wednesday, July 02, 2008 6:36 PM
To: Greenblatt, Alan
Cc: [email protected]
Subject: RE: JESS: Modifying a fact from the current activation


Activation records seem more like part of the implementation than
something to use in ordinary code.  If more than one fact is part of
the activation record, then it may be tricky to identify the fact to
modify.  Perhaps the matching facts could be passed as additional
parameters to deffunctions.  The ModClass1 rule below would become:

(defrule ModClass1
    ?Class1 <-
    (Class1
        (A ?a)
        (B $? ?var1 $?))
    =>
    (modify ?Class1 (A "123")))

Bob Kirby

At 08:55 AM 7/2/2008, Greenblatt, Alan wrote:


        Got it, thanks very much.  I'd agree, adding this to the
Javadoc for
        jess.Token.fact() would be a great idea.
        
        - Alan 
        
        -----Original Message-----
        From: [EMAIL PROTECTED] [
mailto:[EMAIL PROTECTED]
<mailto:[EMAIL PROTECTED]> ]
        On Behalf Of Ernest Friedman-Hill
        Sent: Tuesday, July 01, 2008 5:52 PM
        To: jess-users
        Subject: Re: JESS: Modifying a fact from the current
activation
        
        Hi Alan:
        
        To make a long story short: you need to call getIcon() on the
Fact
        instances you extract here, and use the new Facts returned by
them. As
        the Javadoc for getIcon() says
        
             Return the canonical representation of this Fact object.
For most
        Facts, this returns "this", but for certain Facts -- in
particular,
        for Facts extracted from jess.Token
             objects -- it may return another object. If you are
examining a
        jess.Token object and obtain a reference to a Fact from that
Token,
        then call getIcon() to "canonicalize"
             that Fact before using it.
        
        I should add a note about this issue to the Javadoc for
        jess.Token.fact().
        
        For those interested in the underlying explanation: the facts
returned
        from Token.fact() may -- in the case of a fact with a
multifield that
        is explicitly matched by the rule -- return not the "actual"
fact, but
        a sort of "view" of the fact, that describes how the
multifield is
        matched. The getIcon() method returns the "actual" fact
associated
        with the view.
        
        
        On Jul 1, 2008, at 5:04 PM, Greenblatt, Alan wrote:
        

                I have a series of rules which call a Java user
function when they  
                fire which among other things, sometimes needs to get
the list of  
                facts which caused the rule to fire and then modify a
certain slot  
                in those facts.
                
                Perhaps I have a misunderstanding of how the current
activation  
                works ((engine) getThisAcivation), but I was under the
impression  
                that if you get the Token from the Activation, you can
get at the  
                Facts which contributed to the current rule firing.
                
                I've simulated this with the following simple code,
which produces  
                an exception:
                (deftemplate Class1
                    (slot A)
                    (multislot B))
                
                (defrule ModClass1
                    (Class1
                        (A ?a)
                        (B $? ?var1 $?))
                =>
                    (bind ?token (((engine) getThisActivation)
getToken))
                    (bind ?fact1 (?token fact 0))
                    (modify ?fact1 (A "123")))
                
                (reset)
                
                (assert
                    (Class1
                        (A "abc")
                        (B "def")))
                
                (run)
                
                When run this, I get the following exception: Fact
object not in  
                working memory (MAIN::Class1 (A "abc") (B "def" )).
                
                Evidently, this is because ?fact1 is not identical to
the Fact  
                returned from:
                
                        (bind ?fact2 ((engine) findFactByID (?fact1
getFactId)))
                
                It turns out that if I modify ?fact2 instead of
?fact1, I'm good to  
                go.  Can someone please explain to me what is going on
here?  Why is  
                fact2 different from fact1?
                
                Here's a version of the code from above that works
just fine:
                
                (deftemplate Class1
                    (slot A)
                    (multislot B))
                
                (defrule ModClass1
                    (Class1
                        (A ?a)
                        (B $? ?var1 $?))
                =>
                    (bind ?token (((engine) getThisActivation)
getToken))
                    (bind ?fact1 (?token fact 0))
                    (bind ?fact2 ((engine) findFactByID (?fact1
getFactId)))
                    (modify ?fact2 (A "123")))
                
                (reset)
                
                (assert
                    (Class1
                        (A "abc")
                        (B "def")))
                
                (run)
                
                
                Thanks very much,
                
                Alan


        ---------------------------------------------------------
        Ernest Friedman-Hill
        Informatics & Decision Sciences, Sandia National Laboratories
PO Box
        969, MS 9012, Livermore, CA 94550 http://www.jessrules.com

Reply via email to