Hi David,
Jess is expecting Rocky to behave according to the Java Language Spec
regarding the behaviour of equals() with respect to
hashCode(). Briefly, if two objects are equal(), they -must- have the
same hashCode(); the JLS requires this of any class that implements
equals() or hashCode(). Otherwise other code has a license to
misbehave when it handles objects of your class -- and that's what's
happening here. If you add
public int hashCode() {
return v_name.hashCode();
}
to Rocky, you'll find Jess magically starts working as expected.
The problem is cropping up in the Rete memories, which use hashCode()
to sort objects. In this particular case, the boris fact was being
stored in a bin in defrule schtum's join node's right memory according
to the hashCode of the Rocky object. Because this hashCode didn't
match the one from the rocky fact, the test was never even being
done.
This is an interesting window into how Jess works. Jess dynamically
decides how to index each Rete memory based on the tests it has to
do. In this case, that join node had to compare the contents of the
key slots in the two facts, so Jess decided to index the tokens in
both memories according to the contents of that slot. If there's only
two facts, this doesn't accomplish much; but imagine if there were
1000. Jess could skip most if not all of the equals() calls, since
most Rocky objects would be eliminated by their hashCode.
Anyway, I should add something about hashCode/equals to the manual.
>From the Java API docs:
public int hashCode()
Returns a hash code value for the object. This method is
supported for the benefit of hashtables such as those provided by
java.util.Hashtable.
The general contract of hashCode is:
Whenever it is invoked on the same object more than once
during an execution of a Java application, the hashCode
method must consistently return the same integer, provided no
information used in equals comparisons on the object is
modified. This integer need not remain consistent from one
execution of an application to another execution of the same
application.
If two objects are equal according to the equals(Object)
method, then calling the hashCode method on each of the two
objects must produce the same integer result.
It is not required that if two objects are unequal according
to the equals(java.lang.Object) method, then calling the
hashCode method on each of the two objects must produce
distinct integer results. However, the programmer should be
aware that producing distinct integer results for unequal
objects may improve the performance of hashtables.
As much as is reasonably practical, the hashCode method defined
by class Object does return distinct integers for distinct
objects. (This is typically implemented by converting the
internal address of the object into an integer, but this
implementation technique is not required by the JavaTM
programming language.)
Returns:
a hash code value for this object.
See Also:
equals(java.lang.Object), Hashtable
"David E. Young" wrote:
>
> >>>>> "Ernest" == ejfried <[EMAIL PROTECTED]> writes:
>
> Ernest> Hi David, Jess is intended to behave the way you expect --
> Ernest> calling equals() to match objects...
>
> Ernest> Nevertheless, something unexpected is happening for you. Try
> Ernest> to produce a full, minimal working example that shows the
> Ernest> behaviour and send it along. I'll be glad to have a look.
>
> Hello Ernest. I've enclosed a self-contained example that
illustrates
> the trouble I mentioned. There's a small Java class and a file of
Jess
> code. After loading rocky.clp, you'll notice that only rule
> MORE-SCHTUM is activated.
>
> I've stared at this for awhile and can't for the life of me see
> anything amiss. Thanks for taking a look.
>
> Regards,
>
> --
> -----------------------------------------------------------------
> David E. Young
> Fujitsu Network Communications (defun real-language? (lang)
> ([EMAIL PROTECTED]) (eq lang 'LISP))
>
> "The fact that ... we still
> live well cannot ease the pain of
> feeling that we no longer live nobly."
> -- John Updike
>
> -------- cut here -----------------
>
> ;;; file rocky.clp
>
> (deftemplate rocky
> (slot key)
> (slot value))
>
> (deftemplate boris
> (slot key)
> (slot value))
>
> (defrule schtum
> (rocky (key ?key))
> (boris (key ?key))
> =>
> (printout t "schtum fired." crlf))
>
> (defrule more-schtum
> (rocky (key ?key))
> (boris (key ?k&:(eq ?k ?key)))
> =>
> (printout t "more-schtum fired." crlf))
>
> (watch all)
>
> (assert (rocky (key (new Rocky "rocky"))))
> (assert (boris (key (new Rocky "rocky"))))
>
> // file Rocky.java
>
> public class Rocky {
> public Rocky(String name)
> {
> v_name = name;
> v_tag = 1;
> }
>
> public boolean equals(Object obj)
> {
> if (! (obj instanceof Rocky)) {
> return false;
> }
>
> Rocky r = (Rocky) obj;
>
> return (v_name.equals(r.v_name) && v_tag == r.v_tag);
> }
>
> private String v_name;
> private int v_tag;
> }
>
---------------------------------------------------------
Ernest Friedman-Hill
Distributed Systems Research Phone: (925) 294-2154
Sandia National Labs FAX: (925) 294-2234
Org. 8920, MS 9012 [EMAIL PROTECTED]
PO Box 969 http://herzberg.ca.sandia.gov
Livermore, CA 94550
---------------------------------------------------------------------
To unsubscribe, send the words 'unsubscribe jess-users [EMAIL PROTECTED]'
in the BODY of a message to [EMAIL PROTECTED], NOT to the
list (use your own address!) List problems? Notify [EMAIL PROTECTED]
---------------------------------------------------------------------