Hi all - <div><br></div><div>I have a couple of questions on how hash works.  What I am trying to do is that I am using a struct as the hash key.  The struct has the following definition: </div><div><br></div><blockquote class="webkit-indent-blockquote" style="margin: 0 0 0 40px; border: none; padding: 0px;">
<div><font class="Apple-style-span" face="&#39;courier new&#39;, monospace">(define-struct foo (name)) ;; there are other fields but simplified for this exercise </font></div></blockquote><div><br></div><div>The name field holds a symbol.  Because my actual struct holds quite a bit of complex structure that my code does not hold elsewhere, instead of trying to keep another hash that holds the mapping between the name and the struct, I want to make the name and the struct equivalent from hash&#39;s perspective, so I can pass in the symbol to the hash and it will be mapped to the right struct that maps to the corresponding value. </div>
<div><br></div><div>After much experimentation, I achieve the above goal with the following: </div><div><br></div><div>1 - leverage <font class="Apple-style-span" face="&#39;courier new&#39;, monospace">prop:equal+hash</font> property.  This defines an <font class="Apple-style-span" face="&#39;courier new&#39;, monospace">equal?</font>, <font class="Apple-style-span" face="&#39;courier new&#39;, monospace">equal-hash-code</font>, and <font class="Apple-style-span" face="&#39;courier new&#39;, monospace">equal-secondary-hash-code</font> for the struct.  My definition of foo is updated as follows:</div>
<div><br></div><blockquote class="webkit-indent-blockquote" style="margin: 0 0 0 40px; border: none; padding: 0px;"><div><div><font class="Apple-style-span" face="&#39;courier new&#39;, monospace"><div>(define-struct foo (name)</div>
<div>  #:property prop:equal+hash </div><div>  (let () </div><div>    (define (equal/foo? $s1 $s2 recur) </div><div>      (equal? (foo-name $s1) (foo-name $s2))) </div><div>    (define (equal-hash-code/foo $s recur) </div>
<div>      (- (equal-hash-code (foo-name $s)) <b>35</b>)) </div><div>    (define (equal-secondary-hash-code/foo $s recur) </div><div>      (equal-secondary-hash-code $s))</div><div>    (list equal/foo? equal-hash-code/foo equal-secondary-hash-code/foo)))</div>
</font></div></div></blockquote><div><br></div><div>What&#39;s interesting is that I need to adjust the value from equal-hash-code by 35 in order to get (equal-hash-code &#39;test) and (equal-hash-code (make-foo &#39;test)) to be the same.  For equal-secondary-hash-code such adjustment is not required.  So the first question - why do equal-hash-code require such adjustment (and why 35)? </div>
<div><br></div><div>Now - I thought that hash-ref simply compares the hash-code of the key, but that alone does not appear to be enough, as hash-ref seem to also dictate having the same types for the key, so I have to add one extra struct (called href below) to wrap around the keys: </div>
<div><br></div><blockquote class="webkit-indent-blockquote" style="margin: 0 0 0 40px; border: none; padding: 0px;"><div><div><font class="Apple-style-span" face="&#39;courier new&#39;, monospace">(define-struct href (inner) </font></div>
</div><div><div><font class="Apple-style-span" face="&#39;courier new&#39;, monospace">  #:property prop:equal+hash </font></div></div><div><div><font class="Apple-style-span" face="&#39;courier new&#39;, monospace">  (let () </font></div>
</div><div><div><font class="Apple-style-span" face="&#39;courier new&#39;, monospace">    (define (equal/href? $s1 $s2 recur)</font></div></div><div><div><font class="Apple-style-span" face="&#39;courier new&#39;, monospace">      (equal? (equal-hash-code $s1) (equal-hash-code $s2)))</font></div>
</div><div><div><font class="Apple-style-span" face="&#39;courier new&#39;, monospace">    (define (equal-hash-code/href $s recur) </font></div></div><div><div><font class="Apple-style-span" face="&#39;courier new&#39;, monospace">      (equal-hash-code (href-inner $s))) </font></div>
</div><div><div><font class="Apple-style-span" face="&#39;courier new&#39;, monospace">    (define (equal-secondary-hash-code/href $s recur) </font></div></div><div><div><font class="Apple-style-span" face="&#39;courier new&#39;, monospace">      (equal-secondary-hash-code (href-inner $s)))</font></div>
</div><div><div><font class="Apple-style-span" face="&#39;courier new&#39;, monospace">    (list equal/href? equal-hash-code/href equal-secondary-hash-code)))</font></div></div></blockquote><div><br></div><div>I did not need to adjust the equal-hash-code for this object (not sure why here either).  And now I can finally do the following: </div>
<div><br></div><blockquote class="webkit-indent-blockquote" style="margin: 0 0 0 40px; border: none; padding: 0px;"><div><div><font class="Apple-style-span" face="&#39;courier new&#39;, monospace">(hash-ref (make-immutable-hash (list (cons (make-href (make-foo &#39;test)) &#39;we-have-the-value)))</font></div>
</div><div><div><font class="Apple-style-span" face="&#39;courier new&#39;, monospace">          (make-href &#39;test) &#39;we-do-not-have-the-value) </font></div></div><div><font class="Apple-style-span" face="&#39;courier new&#39;, monospace">;; =&gt; &#39;we-have-the-value </font></div>
</blockquote><div><br></div><div>So it seems that hash-ref by default also checks the type of the key besides checking their hash-code - unless they have the same type, the keys will not match even with the same hash-code.  Is that correct?</div>
<div><br></div><div>Any thoughts are appreciated.  Thanks.</div><div>yc</div><div><br></div>