2.6 Wrapper Types
(require rebellion/type/wrapper) | package: rebellion |
A wrapper type is a kind of data type for values that are simple wrappers around other values. An instance of a wrapper type has a single field containing the wrapped value, and two instances of the same wrapper type are equal? if they wrap equal? values. Wrapper types are useful when the same kind of data is used in many different ways that need to be distinguished.
(define-wrapper-type celsius) (define-wrapper-type fahrenheit) (define/contract (celsius->fahrenheit c) (-> celsius? fahrenheit?) (fahrenheit (+ (* (celsius-value c) 9/5) 32)))
> (celsius->fahrenheit (celsius 0)) (fahrenheit 32)
> (celsius->fahrenheit (celsius 100)) (fahrenheit 212)
> (celsius->fahrenheit (fahrenheit 100)) celsius->fahrenheit: contract violation
expected: celsius?
given: (fahrenheit 100)
in: the 1st argument of
(-> celsius? fahrenheit?)
contract from:
(function celsius->fahrenheit)
blaming: top-level
(assuming the contract is correct)
at: eval:5:0
syntax
(define-wrapper-type 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-wrapper-descriptor? (listof (cons/c struct-type-property? any/c)))
inspector-expr : inspector?
predicate-id, which defaults to id? —
a predicate function that returns #t when given instances of the created type and returns #f otherwise. constructor-id, which defaults to constructor:id —
a wrapper constructor that wraps a value and returns an instance of the created type. accessor-id, which defaults to id-value —
a wrapper accessor that unwraps instances of the created type and returns their underlying value. 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 unwraps instances of the created type and matches their contents against a subpattern.
Additionally, unless #:omit-root-binding is specified, the original id is bound to a wrapper 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-wrapper-implementation for more information about these parameters.
> (define-wrapper-type seconds) > (seconds 10) (seconds 10)
> (seconds-value (seconds 25)) 25
> (seconds? (seconds 10)) #t
> (match-define (seconds (? even? x)) (seconds 10)) > (match-define (seconds (? even? x)) (seconds 25)) match-define: no matching clause for (seconds 25)
2.6.1 Wrapper Type Information
procedure
(wrapper-type? v) → boolean?
v : any/c
procedure
(wrapper-type name [ #:predicate-name predicate-name #:constructor-name constructor-name #:accessor-name accessor-name]) → wrapper-type? name : 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
(wrapper-type-name type) → interned-symbol?
type : wrapper-type?
procedure
type : wrapper-type?
procedure
type : wrapper-type?
procedure
type : wrapper-type?
2.6.2 Wrapper Type Descriptors
The type descriptor for a wrapper type contains two functions that implement the type:
A wrapper constructor that accepts one argument and constructs a wrapper instance.
A wrapper accessor that accepts an instance of the wrapper type and returns the value inside the instance.
These functions can be used to dynamically construct and inspect instances of arbitrary wrapper types at runtime, assuming the type’s descriptor is initialized.
procedure
(wrapper-descriptor? v) → boolean?
v : any/c
procedure
v : any/c
procedure
v : any/c
procedure
(make-wrapper-implementation type [ #:property-maker prop-maker #:inspector inspector]) → initialized-wrapper-descriptor? type : wrapper-type?
prop-maker :
(-> uninitialized-wrapper-descriptor? (listof (cons/c struct-type-property? any/c))) = default-wrapper-properties inspector : inspector? = (current-inspector)
procedure
(wrapper-descriptor-type descriptor) → wrapper-type?
descriptor : wrapper-descriptor?
procedure
(wrapper-descriptor-predicate descriptor) → predicate/c
descriptor : wrapper-descriptor?
procedure
(wrapper-descriptor-constructor descriptor)
→ (-> any/c (wrapper-descriptor-predicate descriptor)) descriptor : wrapper-descriptor?
procedure
(wrapper-descriptor-accessor descriptor)
→ (-> (wrapper-descriptor-predicate descriptor) any/c) descriptor : wrapper-descriptor?
procedure
(default-wrapper-properties descriptor)
→ (listof (cons/c struct-type-property? any/c)) descriptor : wrapper-descriptor?
procedure
(default-wrapper-equal+hash descriptor) → equal+hash/c
descriptor : wrapper-descriptor?
procedure
(default-wrapper-custom-write descriptor)
→ custom-write-function/c descriptor : wrapper-descriptor?
2.6.3 Wrapper Type Bindings
(require rebellion/type/wrapper/binding) | |
package: rebellion |
A wrapper type binding is a type binding for a wrapper type. Wrapper type bindings contain compile-time information about the wrapper type’s name and runtime bindings for its predicate, type descriptor, and other runtime components. To extract a wrapper type binding bound by define-wrapper-type, use the wrapper-id syntax class.
procedure
(wrapper-binding? v) → boolean?
v : any/c
syntax class
type —
an attribute bound to a compile-time wrapper-type? value describing the type. binding —
an attribute bound to the compile-time wrapper-binding? value extracted from the matched identifier. name —
a pattern variable bound to the wrapper type’s name, as a quoted symbol. descriptor —
a pattern variable bound to the wrapper type’s runtime type descriptor. predicate —
a pattern variable bound to the wrapper type’s runtime type predicate. constructor —
a pattern variable bound to the wrapper type’s runtime wrapper constructor. accessor —
a pattern variable bound to the wrapper type’s runtime wrapper accessor.
(require (for-syntax rebellion/type/wrapper/binding)) (define-simple-macro (wrapper-predicate wrapper:wrapper-id) wrapper.predicate) (define-wrapper-type fahrenheit) (wrapper-predicate fahrenheit) #<procedure:fahrenheit?>
procedure
(wrapper-binding-type binding) → wrapper-type?
binding : wrapper-binding?
procedure
(wrapper-binding-descriptor binding) → identifier?
binding : wrapper-binding?
procedure
(wrapper-binding-predicate binding) → identifier?
binding : wrapper-binding?
procedure
(wrapper-binding-constructor binding) → identifier?
binding : wrapper-binding?
procedure
(wrapper-binding-accessor binding) → identifier?
binding : wrapper-binding?