Forge gen:equal+hash and gen:custom-write to provide them from racket/base.

This commit is contained in:
Vincent St-Amour 2012-05-23 17:54:58 -04:00
parent c21813cebf
commit 11dc825126
10 changed files with 64 additions and 75 deletions

View File

@ -4,8 +4,7 @@
unstable/wrapc) unstable/wrapc)
racket/contract/base racket/contract/base
racket/dict racket/dict
racket/vector racket/vector)
racket/struct)
(define (make-gvector #:capacity [capacity 10]) (define (make-gvector #:capacity [capacity 10])
(gvector (make-vector capacity #f) 0)) (gvector (make-vector capacity #f) 0))

View File

@ -27,7 +27,6 @@
racket/promise racket/promise
racket/bool racket/bool
racket/stream racket/stream
racket/struct
racket/sequence racket/sequence
racket/local racket/local
racket/system racket/system
@ -60,7 +59,6 @@
racket/promise racket/promise
racket/bool racket/bool
racket/stream racket/stream
racket/struct
racket/sequence racket/sequence
racket/local racket/local
racket/system) racket/system)

View File

@ -11,6 +11,7 @@
"struct.rkt" "struct.rkt"
"cert.rkt" "cert.rkt"
"submodule.rkt" "submodule.rkt"
"generic-interfaces.rkt"
(for-syntax "stxcase-scheme.rkt")) (for-syntax "stxcase-scheme.rkt"))
(#%provide (all-from-except "pre-base.rkt" (#%provide (all-from-except "pre-base.rkt"
@ -36,6 +37,7 @@
(all-from "namespace.rkt") (all-from "namespace.rkt")
(all-from "cert.rkt") (all-from "cert.rkt")
(all-from "submodule.rkt") (all-from "submodule.rkt")
(all-from "generic-interfaces.rkt")
(for-syntax syntax-rules syntax-id-rules ... _) (for-syntax syntax-rules syntax-id-rules ... _)
(rename -open-input-file open-input-file) (rename -open-input-file open-input-file)
(rename -open-output-file open-output-file) (rename -open-output-file open-output-file)

View File

@ -1,7 +1,6 @@
#lang racket/base #lang racket/base
(require racket/private/generics ; to avoid circular dependencies (require racket/private/generics ; to avoid circular dependencies
racket/struct
(for-syntax racket/base)) (for-syntax racket/base))
(define-generics (dict gen:dict prop:dict dict? #:defined-table dict-def-table (define-generics (dict gen:dict prop:dict dict? #:defined-table dict-def-table

View File

@ -0,0 +1,56 @@
(module generic-interfaces "pre-base.rkt"
;; Defines (forgeries of) generic interfaces that correspond to struct
;; properties that come from racket/base.
;; Since racket/base can't depend on racket/generics, we can't use
;; `define-generics' to build these generic interfaces. Thus we must
;; forge them.
(#%require (for-syntax '#%kernel))
(#%provide gen:equal+hash gen:custom-write)
(define-values (prop:gen:equal+hash equal+hash? gen:equal+hash-acc)
(make-struct-type-property
'prop:gen:equal+hash
(lambda (v si)
(if (and (vector? v)
(= 3 (vector-length v))
(procedure? (vector-ref v 0))
(procedure-arity-includes? (vector-ref v 0) 3)
(procedure? (vector-ref v 1))
(procedure-arity-includes? (vector-ref v 1) 2)
(procedure? (vector-ref v 2))
(procedure-arity-includes? (vector-ref v 2) 2))
v
(raise-type-error 'guard-for-prop:gen:equal+hash
"vector of three procedures (arities 3, 2, 2)"
v)))
(list (cons prop:equal+hash vector->list))))
(define-syntax gen:equal+hash
(list (quote-syntax prop:gen:equal+hash)
(quote-syntax equal-proc)
(quote-syntax hash-proc)
(quote-syntax hash2-proc)))
(define-values (prop:gen:custom-write gen:custom-write? gen:custom-write-acc)
(make-struct-type-property
'prop:gen:custom-write
(lambda (v si)
(if (and (vector? v)
(= 1 (vector-length v))
(procedure? (vector-ref v 0))
(procedure-arity-includes? (vector-ref v 0) 3))
v
(raise-type-error 'guard-for-prop:gen:custom-write
"vector of one procedure (arity 3)"
v)))
(list (cons prop:custom-write (lambda (v) (vector-ref v 0))))))
(define-syntax gen:custom-write
(list (quote-syntax prop:gen:custom-write)
(quote-syntax write-proc)))
)

View File

@ -1,56 +0,0 @@
#lang racket/base
;; Provides generic interfaces that correspond to struct properties
;; that live in racket/base
(require racket/private/generics)
(provide gen:equal+hash)
(define-values (prop:gen:equal+hash equal+hash? gen:equal+hash-acc)
(make-struct-type-property
'prop:gen:equal+hash
(lambda (v si)
(unless (and (vector? v)
(= 3 (vector-length v))
(procedure? (vector-ref v 0))
(procedure-arity-includes? (vector-ref v 0) 3)
(procedure? (vector-ref v 1))
(procedure-arity-includes? (vector-ref v 1) 2)
(procedure? (vector-ref v 2))
(procedure-arity-includes? (vector-ref v 2) 2))
(raise-type-error 'guard-for-prop:gen:equal+hash
"vector of three procedures (arities 3, 2, 2)"
v))
v)
(list (cons prop:equal+hash vector->list))))
(define-generics (equal+hash gen:equal+hash prop:gen:equal+hash equal+hash?
#:defined-table equal+hash-def-table
#:prop-defined-already? gen:equal+hash-acc)
(equal-proc equal+hash rhs equal?/recur)
(hash-proc equal+hash equal-hash-code/recur)
(hash2-proc equal+hash equal-secondary-hash-code/recur))
(provide gen:custom-write)
(define-values (prop:gen:custom-write gen:custom-write? gen:custom-write-acc)
(make-struct-type-property
'prop:gen:custom-write
(lambda (v si)
(unless (and (vector? v)
(= 1 (vector-length v))
(procedure? (vector-ref v 0))
(procedure-arity-includes? (vector-ref v 0) 3))
(raise-type-error 'guard-for-prop:gen:custom-write
"vector of one procedure (arity 3)"
v))
v)
(list (cons prop:custom-write (lambda (v) (vector-ref v 0))))))
(define-generics (custom-write gen:custom-write prop:gen:custom-write
gen:custom-write?
#:defined-table custom-write-def-table
#:prop-defined-already? gen:custom-write-acc)
(write-proc custom-write port mode))

View File

@ -4,9 +4,6 @@
@(define bool-eval (make-base-eval)) @(define bool-eval (make-base-eval))
@(bool-eval '(require racket/bool)) @(bool-eval '(require racket/bool))
@(define struct-eval (make-base-eval))
@(struct-eval '(require racket/struct))
@title[#:tag "booleans"]{Booleans and Equality} @title[#:tag "booleans"]{Booleans and Equality}
True and false @deftech{booleans} are represented by the values True and false @deftech{booleans} are represented by the values
@ -135,10 +132,6 @@ type. @racket[gen:equal+hash] should be used instead. Accepts a list of
three procedures that correspond to the methods of @racket[gen:equal+hash]. three procedures that correspond to the methods of @racket[gen:equal+hash].
} }
@section{Extensible Equality and Hashing}
@note-lib[racket/struct]
@defthing[gen:equal+hash any/c]{ @defthing[gen:equal+hash any/c]{
A @tech{generic interface} (see @secref["struct-generics"]) that A @tech{generic interface} (see @secref["struct-generics"]) that
supplies an equality predicate and hashing functions for a structure supplies an equality predicate and hashing functions for a structure
@ -208,7 +201,7 @@ property, then the @racket[prop:impersonator-of] property takes precedence over
@racket[gen:equal+hash] if the property value's procedure returns a @racket[gen:equal+hash] if the property value's procedure returns a
non-@racket[#f] value when applied to the structure. non-@racket[#f] value when applied to the structure.
@examples[ #:eval struct-eval @examples[
(define (farm=? farm1 farm2 recursive-equal?) (define (farm=? farm1 farm2 recursive-equal?)
(and (= (farm-apples farm1) (and (= (farm-apples farm1)
(farm-apples farm2)) (farm-apples farm2))

View File

@ -1,6 +1,6 @@
#lang racket/base #lang racket/base
(require racket/generics racket/struct (require racket/generics
(only-in racket/dict (only-in racket/dict
gen:dict prop:dict gen:dict prop:dict
dict? dict?

View File

@ -1,6 +1,6 @@
#lang racket #lang racket/base
(require racket/struct) (require racket/port)
(struct loud (v) (struct loud (v)
#:methods gen:custom-write #:methods gen:custom-write

View File

@ -1,6 +1,4 @@
#lang racket #lang racket/base
(require racket/struct)
;; vectors as method tables ;; vectors as method tables
(struct kons (kar kdr) (struct kons (kar kdr)