[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

equal hashing bug in mcl 2.0b1p3



In pursuing the bug I reported to bug-mcl last night, I have
managed to track the problem down to the way equal-hash-tables
and sxhash handle s-expressions with defstruct instances embedded
in them.  Specifically, though EQUAL is defined to work like
EQL wrt structures, sxhash's output value (and the behavior of
gethash) changes if you mutate a field of the structure.
Here's an example:

(progn
  (defstruct (foo) bar)
  (setq frob (make-foo :bar nil))
  (setq eqh (make-hash-table))
  (setq equalh (make-hash-table :test #'equal))

  (setf (gethash frob eqh) "Yes")
  (setf (gethash frob equalh) "Yes")

  (gethash frob eqh)    ;;==> "Yes"
  (gethash frob equalh) ;;==> "Yes"

  (sxhash frob) ;;==> 10354986
  
  (setf (foo-bar frob) 2349)

  (sxhash frob) ;;==> 10357335

  (gethash frob eqh)    ;;=> "Yes"
  (gethash frob equalh) ;;=> NIL
  )

;;; interestingly, if I do a (gethash frob equalh) BEFORE
;;; I do the (setf (foo-bar frob) 2349) the (gethash frob equalh)
;;; AFTER it works!  (This is probably due to the caching you seem to be
;;; doing in the hash table implementation.)

Now, since EQUAL is defined to be true of two objects if
EQL is, one should be able to conclude that if gethash of an
object in an EQL table wins then gethash of the same object
in an EQUAL table should also win.  The example above demonstrates
that this doesn't work in MCL 2.0b1p3.
The difference in behavior due to the caching is further evidence of
the bug.

I'd appreciate knowing of any patches/workarounds for this problem.

For my current application, I am able to arrange that all structures
in hash keys are immutable, which avoids the problem, but begs the
general question.

Thanks,

-- Bob Hall (hall@allegra.att.com)