2.2 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 | #:descriptor-name descriptor-id | #:predicate-name predicate-id | #:constructor-name constructor-id | #:accessor-name accessor-id | #:pattern-name pattern-id | #:property-maker prop-maker-expr | #:inspector inspector-expr
prop-maker-expr :
(-> uninitialized-tuple-descriptor? (listof (cons/c struct-type-property? any/c)))
inspector-expr : inspector?
constructor-id, which defaults to constructor:id —
a tuple constructor 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 —
a field accessor function that returns the value for field-id when given an instance of the created type. accessor-id, which defaults accessor:id —
a tuple accessor that accepts an instance of the created type and an integer indicating which field to access, then returns the value of that field. descriptor-id, which defaults to descriptor:id —
the type descriptor for 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 a tuple type binding for the created type. The binding behaves like pattern-id when used in match patterns and like 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.
The prop-maker-expr is used to add structure type properties to the created type, and inspector-expr is used to determine the inspector that will control the created type. See make-tuple-implementation for more information about these parameters.
> (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.2.1 Tuple Type Information
procedure
(tuple-type? v) → boolean?
v : any/c
procedure
(tuple-type name fields [ #:predicate-name predicate-name #:constructor-name constructor-name #:accessor-name accessor-name]) → tuple-type? name : interned-symbol? fields : (sequence/c interned-symbol?) 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-fields type)
→ (vectorof interned-symbol? #:immutable #t) type : tuple-type?
procedure
type : tuple-type?
procedure
type : tuple-type?
procedure
(tuple-type-accessor-name type) → interned-symbol?
type : tuple-type?
procedure
(tuple-type-size type) → natural?
type : tuple-type?
2.2.2 Tuple Type Descriptors
The type descriptor for a tuple type contains two functions that implement the type:
A tuple constructor that accepts one argument for each field of the tuple type and constructs a tuple instance.
A tuple accessor that accepts an instance of the tuple type and an integer field index, then returns the value of the corresponding field.
These functions can be used to dynamically construct and inspect instances of arbitrary tuple types at runtime, assuming the type’s descriptor is initialized. Note that the descriptor contains a single accessor function that can access any field in the tuple: the per-field accessors created by define-tuple-type are merely convenient wrappers around this accessor.
procedure
(tuple-descriptor? v) → boolean?
v : any/c
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 (list 'x 'y)))) > (define point (tuple-descriptor-constructor point-descriptor)) > (define point-x (make-tuple-field-accessor point-descriptor 0)) > (define point-y (make-tuple-field-accessor point-descriptor 1)) > (point 42 888) (point 42 888)
> (point-x (point 42 888)) 42
> (point-y (point 42 888)) 888
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?
procedure
(make-tuple-field-accessor descriptor pos)
→ (-> (tuple-descriptor-predicate descriptor) any/c) descriptor : tuple-descriptor? pos : natural?
procedure
(default-tuple-properties descriptor)
→ (listof (cons/c struct-type-property? any/c)) descriptor : 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.2.3 Tuple Type Bindings
(require rebellion/type/tuple/binding) | package: rebellion |
A tuple type binding is a type binding for a tuple type. Tuple type bindings contain compile-time information about the tuple type’s name and fields, as well as runtime bindings for its predicate, type descriptor, and other runtime components. To extract a tuple type binding bound by define-tuple-type, use the tuple-id syntax class.
procedure
(tuple-binding? v) → boolean?
v : any/c
syntax class
type —
an attribute bound to a compile-time tuple-type? value describing the type. binding —
an attribute bound to the compile-time tuple-binding? value extracted from the matched identifier. name —
a pattern variable bound to the tuple type’s name, as a quoted symbol. descriptor —
a pattern variable bound to the tuple type’s runtime type descriptor. predicate —
a pattern variable bound to the tuple type’s runtime type predicate. constructor —
a pattern variable bound to the tuple type’s runtime tuple constructor. accessor —
a pattern variable bound to the tuple type’s runtime tuple accessor. field ... —
a pattern variable bound to the tuple’s field identifiers. field-name ... —
a pattern variable bound to the tuple’s field names, as quoted symbols. field-accessor ... —
a pattern variable bound to the tuple type’s per-field runtime field accessors.
(require (for-syntax rebellion/type/tuple/binding)) (define-simple-macro (tuple-field-names tuple:tuple-id) (list tuple.field-name ...)) (define-tuple-type point (x y z)) (tuple-field-names point) '(x y z)
procedure
(tuple-binding-type binding) → tuple-type?
binding : tuple-binding?
procedure
(tuple-binding-descriptor binding) → identifier?
binding : tuple-binding?
procedure
(tuple-binding-predicate binding) → identifier?
binding : tuple-binding?
procedure
(tuple-binding-constructor binding) → identifier?
binding : tuple-binding?
procedure
(tuple-binding-accessor binding) → identifier?
binding : tuple-binding?
procedure
(tuple-binding-fields binding)
→ (vectorof identifier? #:immutable #t) binding : tuple-binding?
procedure
(tuple-binding-field-accessors binding)
→ (vectorof identifier? #:immutable #t) binding : tuple-binding?
2.2.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