add section to guide on structure equality

svn: r14049
This commit is contained in:
Matthew Flatt 2009-03-11 03:40:42 +00:00
parent 9a900d5100
commit 0c36eb9ae6
2 changed files with 67 additions and 1 deletions

View File

@ -188,6 +188,72 @@ can use an opaque structure to encapsulate data, and clients of the
library cannot manipulate the data in the structure except as allowed library cannot manipulate the data in the structure except as allowed
by the library. by the library.
@; ------------------------------------------------------------
@section[#:tag "struct-equal"]{Stucture Comparisons}
A generic @scheme[equal?] comparison automatically recurs on the
fields of a transparent structure type, but @scheme[equal?] defaults
to mere instance identity for opaque structure types:
@def+int[
#:eval posn-eval
(define-struct glass (width height) #:transparent)
(equal? (make-glass 1 2) (make-glass 1 2))
]
@def+int[
#:eval posn-eval
(define-struct lead (width height))
(define slab (make-lead 1 2))
(equal? slab slab)
(equal? slab (make-lead 1 2))
]
To support instances comparisons via @scheme[equal?] without making
the structure type transparent, you can use the @scheme[#:property]
keyword, @scheme[prop:equal+hash], and then a list of three functions:
@def+int[
#:eval posn-eval
(define-struct lead (width height)
#:property
prop:equal+hash
(list (lambda (a b equal?-recur)
(code:comment #, @t{compare @scheme[a] and @scheme[b]})
(and (equal?-recur (lead-width a) (lead-width b))
(equal?-recur (lead-height a) (lead-height b))))
(lambda (a hash-recur)
(code:comment #, @t{compute primary hash code of @scheme[a]})
(+ (hash-recur (lead-width a))
(* 3 (hash-recur (lead-height a)))))
(lambda (a hash2-recur)
(code:comment #, @t{compute secondary hash code of @scheme[a]})
(+ (hash2-recur (lead-width a))
(hash2-recur (lead-height a))))))
(equal? (make-lead 1 2) (make-lead 1 2))
]
The first function in the list implements the @scheme[equal?] test on
two @scheme[lead]s; the third argument to the function is used instead
of @scheme[equal?] for recursive equality testing, so that data cycles
can be handled correctly. The other two functions compute primary and
secondary hash codes for use with @tech{hash tables}:
@interaction[
#:eval posn-eval
(define h (make-hash))
(hash-set! h (make-lead 1 2) 3)
(hash-ref h (make-lead 1 2))
(hash-ref h (make-lead 2 1))
]
The first function provided with @scheme[prop:equal+hash] is not
required to recursively compare the fields of the structure. For
example, a structure type representing a set might implement equality
by checking that the members of the set are the same, independent of
the order of elements in the internal representation. Just take care
that the hash functions produce the same value for any two structure
types that are supposed to be equivalent.
@; ------------------------------------------------------------ @; ------------------------------------------------------------
@section{Structure Type Generativity} @section{Structure Type Generativity}

View File

@ -5,7 +5,7 @@
@title[#:tag "hash-tables"]{Hash Tables} @title[#:tag "hash-tables"]{Hash Tables}
A @defterm{hash table} implements a mapping from keys to values, where A @deftech{hash table} implements a mapping from keys to values, where
both keys and values can be arbitrary Scheme values, and access and both keys and values can be arbitrary Scheme values, and access and
update to the table are normally constant-time operations. Keys are update to the table are normally constant-time operations. Keys are
compared using @scheme[equal?] or @scheme[eq?], depending on whether compared using @scheme[equal?] or @scheme[eq?], depending on whether