2.3 Tuple Types
(require rebellion/type/tuple) | package: rebellion |
A tuple type is a kind of data type for composite values that contain an ordered list of fields. The definition of each tuple type declares how many fields it has and what their names are, although those names are only observable at compile time. Constructing an instance of a tuple type requires passing a positional argument for each field to the type’s constructor. Tuple types are useful when a fixed number of different pieces of data together represent a single logical thing, and there is an obvious order to those pieces.
(define-tuple-type point (x y)) (define/contract (point-distance start end) (-> point? point? real?) (match-define (point x1 y1) start) (match-define (point x2 y2) end) (define dx (- x2 x1)) (define dy (- y2 y1)) (sqrt (+ (sqr dx) (sqr dy))))
> (point-distance (point 0 0) (point 3 4)) 5
> (point-distance (point 0 0) (list 3 4)) point-distance: contract violation
expected: point?
given: '(3 4)
in: the 2nd argument of
(-> point? point? real?)
contract from: (function point-distance)
blaming: top-level
(assuming the contract is correct)
at: eval:3.0
syntax
(define-tuple-type id (field-id ...) option ...)
option = #:omit-root-binding | #:constructor-name constructor-id | #:predicate-name predicate-id | #:pattern-name pattern-id | #:property-maker prop-maker-expr
prop-maker-expr :
(-> uninitialized-tuple-descriptor? (listof (cons/c struct-type-property? any/c)))
constructor-id, which defaults to constructor:id —
a constructor function that accepts one positional argument for each field-id and returns an instance of the created type. predicate-id, which defaults to id? —
a predicate function that returns #t when given instances of the created type and returns #f otherwise. id-field-id for each field-id —
an accessor function that returns the value for field-id when given an instance of the created type. pattern-id, which defaults to pattern:id —
a match expander that deconstructs instances of the created type and matches each field against a subpattern
Additionally, unless #:omit-root-binding is specified, the original id is bound to pattern-id when used in match patterns and to constructor-id when used as an expression. Use #:omit-root-binding when you want control over what id is bound to, such as when creating a smart constructor.
> (define-tuple-type point (x y)) > (point 1 2) (point 1 2)
> (point? (point 1 2)) #t
> (point-x (point 42 0)) 42
> (point-y (point 42 0)) 0
> (match-define (point (? positive? x) (? negative? y)) (point 3 -3))
2.3.1 Tuple Type Information
procedure
(tuple-type? v) → boolean?
v : any/c
procedure
(tuple-type name size [ #:predicate-name predicate-name #:constructor-name constructor-name #:accessor-name accessor-name]) → tuple-type? name : interned-symbol? size : natural? predicate-name : (or/c interned-symbol? #f) = #f constructor-name : (or/c interned-symbol? #f) = #f accessor-name : (or/c interned-symbol? #f) = #f
procedure
(tuple-type-name type) → interned-symbol?
type : tuple-type?
procedure
(tuple-type-size type) → natural?
type : tuple-type?
procedure
type : tuple-type?
procedure
type : tuple-type?
procedure
(tuple-type-accessor-name type) → interned-symbol?
type : tuple-type?
2.3.2 Tuple Type Descriptors
procedure
(tuple-descriptor? v) → boolean?
v : any/c
procedure
(tuple-descriptor-type descriptor) → tuple-type?
descriptor : tuple-descriptor?
procedure
(tuple-descriptor-predicate descriptor) → (-> any/c boolean?)
descriptor : tuple-descriptor?
procedure
(tuple-descriptor-constructor descriptor) → procedure?
descriptor : tuple-descriptor?
procedure
(tuple-descriptor-accessor descriptor)
→ (-> (tuple-descriptor-predicate descriptor) natural? any/c) descriptor : tuple-descriptor?
2.3.3 Dynamically Implementing Tuple Types
procedure
(make-tuple-implementation type [ #:guard guard #:inspector inspector #:property-maker prop-maker]) → initialized-tuple-descriptor? type : tuple-type? guard : (or/c procedure? #f) = #f inspector : inspector? = (current-inspector)
prop-maker :
(-> uninitialized-tuple-descriptor? (listof (cons/c struct-type-property? any/c))) = default-tuple-properties
> (define point-descriptor (make-tuple-implementation (tuple-type 'point 2))) > (define point (tuple-descriptor-constructor point-descriptor)) > (define point-x (make-tuple-field-accessor point-descriptor 0 'x)) > (define point-y (make-tuple-field-accessor point-descriptor 1 'y)) > (point 42 888) (point 42 888)
> (point-x (point 42 888)) 42
> (point-y (point 42 888)) 888
procedure
(make-tuple-field-accessor descriptor pos [ name]) → (-> (tuple-descriptor-predicate descriptor) any/c) descriptor : tuple-descriptor? pos : natural?
name : (or/c interned-symbol? #f) = (symbol->string (format "field~a" pos))
procedure
(default-tuple-properties descriptor)
→ (listof (cons/c struct-type-property? any/c)) descriptor : uninitialized-tuple-descriptor?
procedure
(default-tuple-equal+hash descriptor) → equal+hash/c
descriptor : tuple-descriptor?
> (define-tuple-type point (x y) #:property-maker (λ (descriptor) (list (cons prop:equal+hash (default-tuple-equal+hash descriptor))))) > (equal? (point 1 2) (point 1 2)) #t
> (equal? (point 1 2) (point 2 1)) #f
procedure
(default-tuple-custom-write descriptor)
→ custom-write-function/c descriptor : tuple-descriptor?
> (define-tuple-type point (x y) #:property-maker (λ (descriptor) (define custom-write (default-tuple-custom-write descriptor)) (list (cons prop:custom-write custom-write)))) > (point 1 2) (point 1 2)
> (parameterize ([pretty-print-columns 10]) (pretty-print (point 100000000000000 200000000000000)))
(point
100000000000000
200000000000000)
2.3.4 Tuple Chaperones and Impersonators
procedure
(tuple-impersonate instance descriptor [ #:properties properties #:chaperone? chaperone?]) → (tuple-descriptor-predicate descriptor) instance : (tuple-descriptor-predicate descriptor) descriptor : initialized-tuple-descriptor?
properties : (hash/c impersonator-property? any/c #:immutable #t) = empty-hash chaperone? : boolean? = #t