On this page:
define-wrapper-type
2.6.1 Wrapper Type Information
wrapper-type?
wrapper-type
wrapper-type-name
wrapper-type-predicate-name
wrapper-type-constructor-name
wrapper-type-accessor-name
2.6.2 Wrapper Type Descriptors
wrapper-descriptor?
initialized-wrapper-descriptor?
uninitialized-wrapper-descriptor?
make-wrapper-implementation
wrapper-descriptor-type
wrapper-descriptor-predicate
wrapper-descriptor-constructor
wrapper-descriptor-accessor
default-wrapper-properties
default-wrapper-equal+  hash
default-wrapper-custom-write
2.6.3 Wrapper Type Bindings
wrapper-binding?
wrapper-id
wrapper-binding-type
wrapper-binding-descriptor
wrapper-binding-predicate
wrapper-binding-constructor
wrapper-binding-accessor
8.0

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?
Creates a new wrapper type named id and binds the following identifiers:

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.

Examples:
> (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
A predicate for wrapper types.

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
Constructs a wrapper type named name. The optional predicate-name, constructor-name, and accessor-name arguments control the result of object-name on the functions implementing the type. If not provided, predicate-name defaults to name?, constructor-name defaults to constructor:name, and accessor-name defaults to name-value. Two wrapper types constructed with the same arguments are equal?. To make an implementation of a wrapper type, see make-wrapper-implementation.

procedure

(wrapper-type-name type)  interned-symbol?

  type : wrapper-type?

procedure

(wrapper-type-predicate-name type)  interned-symbol?

  type : wrapper-type?

procedure

(wrapper-type-constructor-name type)  interned-symbol?

  type : wrapper-type?

procedure

(wrapper-type-accessor-name type)  interned-symbol?

  type : wrapper-type?
Accessors for the various fields of a wrapper type.

2.6.2 Wrapper Type Descriptors

The type descriptor for a wrapper type contains two functions that implement the type:

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
A predicate for type descriptors of wrapper types.

procedure

(initialized-wrapper-descriptor? v)  boolean?

  v : any/c
A predicate for initialized wrapper type descriptors.

procedure

(uninitialized-wrapper-descriptor? v)  boolean?

  v : any/c
A predicate for uninitialized wrapper type descriptors.

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)
Implements type and returns a type descriptor for the new implementation. The inspector argument behaves the same as in make-struct-type, although there are no transparent or prefab wrapper types. The prop-maker argument is similar to the corresponding argument of make-struct-implementation. By default, wrapper types are created with properties that make them print and compare in a manner similar to transparent structure types — see default-wrapper-properties for details.

procedure

(wrapper-descriptor-type descriptor)  wrapper-type?

  descriptor : wrapper-descriptor?
Returns the wrapper type that descriptor implements.

procedure

(wrapper-descriptor-predicate descriptor)  predicate/c

  descriptor : wrapper-descriptor?
Returns a predicate that returns true when given any wrapper instance created by descriptor. The predicate is specific to descriptor it will not return true for wrapper instances created by any other wrapper descriptors, even if they’re different implementations of the same wrapper type as descriptor. This is because wrapper types are nominal types.

procedure

(wrapper-descriptor-constructor descriptor)

  (-> any/c (wrapper-descriptor-predicate descriptor))
  descriptor : wrapper-descriptor?
Returns the wrapper constructor of the wrapper type implementation represented by descriptor. The constructor accepts one argument and returns an instance of the wrapper type.

procedure

(wrapper-descriptor-accessor descriptor)

  (-> (wrapper-descriptor-predicate descriptor) any/c)
  descriptor : wrapper-descriptor?
Returns the wrapper accessor of the wrapper type implementation represented by descriptor. The accessor accepts wrapper instances created by descriptor and returns the value inside the given instance.

procedure

(default-wrapper-properties descriptor)

  (listof (cons/c struct-type-property? any/c))
  descriptor : wrapper-descriptor?
Returns implementations of prop:equal+hash and prop:custom-write suitable for most wrapper types. This function is called by make-wrapper-implementation when no prop-maker argument is supplied.

procedure

(default-wrapper-equal+hash descriptor)  equal+hash/c

  descriptor : wrapper-descriptor?
Builds an equality-checking function, a hashing function, and a secondary hashing function suitable for use with prop:equal+hash, each of which operate on instances of descriptor by comparing and hashing their wrapped values. This causes equal? to behave roughly the same as it does on transparent structure types. This function is used by default-wrapper-properties to implement prop:equal+hash.

procedure

(default-wrapper-custom-write descriptor)

  custom-write-function/c
  descriptor : wrapper-descriptor?
Constructs a custom write implementation that prints instances of the wrapper type described by descriptor in a manner similar to transparent structures. This function is used by default-wrapper-properties to implement prop:custom-write.

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
A predicate for wrapper type bindings.

syntax class

wrapper-id

A syntax class for wrapper type bindings bound by define-wrapper-type. This class matches any identifier bound with define-syntax to a value satisfying the wrapper-binding? predicate, similar to the static syntax class. Upon a successful match, the wrapper-id class defines the following attributes:
  • 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.

Example:
(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?
Returns the wrapper type that binding is for. When a wrapper type binding is bound with define-syntax, this can be used at compile-time to retrieve the name of the wrapper type.

procedure

(wrapper-binding-descriptor binding)  identifier?

  binding : wrapper-binding?
Returns an identifier that is bound at runtime to the type descriptor for the wrapper type bound by binding. When a wrapper type binding is bound with define-syntax, this can be used in macro-generated code to work with wrapper types dynamically.

procedure

(wrapper-binding-predicate binding)  identifier?

  binding : wrapper-binding?
Returns an identifier that is bound at runtime to the predicate for the wrapper type bound by binding.

procedure

(wrapper-binding-constructor binding)  identifier?

  binding : wrapper-binding?
Returns an identifier that is bound at runtime to the wrapper constructor for the wrapper type bound by binding.

procedure

(wrapper-binding-accessor binding)  identifier?

  binding : wrapper-binding?
Returns an identifier that is bound at runtime to the wrapper accessor for the wrapper type bound by binding.