On this page:
define-object-type
2.7.1 Object Type Information
object-type?
object-type
object-type-name
object-type-fields
object-type-private-fields
object-type-name-field
object-type-name-field-position
object-type-constructor-name
object-type-predicate-name
object-type-accessor-name
object-type-size
2.7.2 Object Type Descriptors
object-descriptor?
initialized-object-descriptor?
uninitialized-object-descriptor?
make-object-implementation
object-descriptor-type
object-descriptor-predicate
object-descriptor-constructor
object-descriptor-accessor
make-object-field-accessor
default-object-properties
default-object-equal+  hash
default-object-custom-write
default-object-name-property
2.7.3 Object Type Bindings
object-binding?
object-id
object-binding-type
object-binding-descriptor
object-binding-predicate
object-binding-constructor
object-binding-accessor
object-binding-fields
object-binding-field-accessors
object-binding-private-fields
object-binding-private-accessors
object-binding-name-field
object-binding-name-accessor
2.7.4 Object Type Chaperones and Impersonators
object-impersonate
8.0

2.7 Object Types

 (require rebellion/type/object) package: rebellion

An object type is a kind of data type for opaque named values. Object types are similar to record types in that they both have an unordered set of fields and a keyword-based constructor. However, object types are intended for encapsulating behavior, not data. In support of this, object types have an automatic #:name field used to implement prop:object-name. Instead of printing their fields, instances of object types print like other named opaque values such as functions and ports and print only their names.

As a rule of thumb, if you want to simply bundle together data then use record types. But if you want to group together functions or other complex objects, and you don’t want to give users access to them, use object types. Examples of object types in Rebellion include converters, comparators, reducers, and transducers.

syntax

(define-object-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
  | #:property-maker prop-maker-expr
  | #:inspector inspector-expr
 
  prop-maker-expr : 
(-> uninitialized-object-descriptor?
    (listof (cons/c struct-type-property? any/c)))
  inspector-expr : inspector?
Creates a new object type named id and binds the following identifiers:

Additionally, unless #:omit-root-binding is specified, the original id is bound to an object type binding for the created type.

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-object-implementation for more information about these parameters.

Examples:
(define-object-type folder (accumulator initial-state))
 
(define (fold sequence folder)
  (define initial-state (folder-initial-state folder))
  (define accumulator (folder-accumulator folder))
  (for/fold ([state initial-state]) ([v sequence])
    (accumulator state v)))
 
(define sum
  (make-folder #:accumulator +
               #:initial-state 0
               #:name 'sum))

 

> sum

#<folder:sum>

> (fold (list 1 2 3 4) sum)

10

2.7.1 Object Type Information

procedure

(object-type? v)  boolean?

  v : any/c
A predicate for object types.

procedure

(object-type name 
  fields 
  [#:name-field name-field 
  #:constructor-name constructor-name 
  #:predicate-name predicate-name 
  #:accessor-name accessor-name]) 
  object-type?
  name : interned-symbol?
  fields : keyset?
  name-field : keyword? = '#:name
  constructor-name : (or/c interned-symbol? #f) = #f
  predicate-name : (or/c interned-symbol? #f) = #f
  accessor-name : (or/c interned-symbol? #f) = #f
Constructs an object type named name and with fields named fields, with name-field used to store the names of instances of the type.

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 make-name, and accessor-name defaults to accessor:name.

This function only constructs the information representing an object type; to implement the type, use make-object-implementation.

procedure

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

  type : object-type?
Returns the name of type.

procedure

(object-type-fields type)  keyset?

  type : object-type?
Returns the set of fields in type, including the name field.

procedure

(object-type-private-fields type)  keyset?

  type : object-type?
Returns the set of fields in type that are hidden from users — that is, every field except for the name field.

procedure

(object-type-name-field type)  keyword?

  type : object-type?
Returns the name field of type.

procedure

(object-type-name-field-position type)  natural?

  type : object-type?
Returns the position of the name field of type.

Returns the name of the constructor for type.

procedure

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

  type : object-type?
Returns the name of the predicate for type.

procedure

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

  type : object-type?
Returns the name of the accessor for type.

procedure

(object-type-size type)  natural?

  type : object-type?
Returns the number of fields (include the name field) in type.

2.7.2 Object Type Descriptors

The type descriptor for an object type contains two functions that implement the type:

These functions can be used to dynamically construct and inspect instances of arbitrary object 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 object: the per-field accessors created by define-object-type are merely convenient wrappers around this accessor.

procedure

(object-descriptor? v)  boolean?

  v : any/c
A predicate for object type descriptors.

procedure

(initialized-object-descriptor? v)  boolean?

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

procedure

(uninitialized-object-descriptor? v)  boolean?

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

procedure

(make-object-implementation type 
  [#:inspector inspector 
  #:property-maker prop-maker]) 
  initialized-object-descriptor?
  type : object-type?
  inspector : inspector? = (current-inspector)
  prop-maker : 
(-> uninitialized-object-descriptor?
    (listof (cons/c struct-type-property? any/c)))
   = default-object-properties
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 object types. The prop-maker argument is similar to the corresponding argument of make-struct-implementation. By default, object types are created with properties that make them print like opaque named objects.

procedure

(object-descriptor-type descriptor)  object-type?

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

procedure

(object-descriptor-predicate descriptor)  predicate/c

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

procedure

(object-descriptor-constructor descriptor)  procedure?

  descriptor : object-descriptor?
Returns the object constructor of the object type implementation represented by descriptor. The constructor accepts one keyword argument for each field in the object type and returns an instance of the object type. All of the constructor’s keyword arguments are mandatory, except for the argument that supplies the instance’s name — that argument defaults to #f if not given.

procedure

(object-descriptor-accessor descriptor)

  (-> (object-descriptor-predicate descriptor) natural? any/c)
  descriptor : object-descriptor?
Returns the object accessor of the object type implementation represented by descriptor. The accessor accepts two arguments: an object instance created by descriptor, and a nonnegative integer less than the number of fields in the object type. The accessor returns the value of the corresponding field in the instance. To access fields by name, first determine the integer index of the field name using the keyset returned by object-type-fields. See also make-object-field-accessor to construct a field-specific accessor function.

procedure

(make-object-field-accessor descriptor 
  field) 
  (-> (object-descriptor-predicate descriptor) any/c)
  descriptor : object-descriptor?
  field : natural?
Constructs a function that accepts an instance of the object type implemented by descriptor and returns the value of the field at position field in the object.

procedure

(default-object-properties descriptor)

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

procedure

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

  descriptor : object-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 object instances created by descriptor. Two instances are equal if and only if the fields of one instance are equal to the fields of the other. This function is used by default-object-properties to implement prop:equal+hash.

procedure

(default-object-custom-write descriptor)

  custom-write-function/c
  descriptor : object-descriptor?
Builds a custom write implementation that prints object instances created by descriptor in a manner similar to other opaque named Racket values, such as functions and ports. Instances are printed as unreadable values and include the name of the instance prefixed by the name of the instance’s type. Anonymous instances only print their type. This function is used by default-object-properties to implement prop:custom-write.

procedure

(default-object-name-property descriptor)  natural?

  descriptor : object-descriptor?
Builds a value suitable for use with prop:object-name that causes object-name to return the name of the instance when used on object instances created by descriptor. This function is used by default-object-properties to implement prop:object-name.

2.7.3 Object Type Bindings

 (require rebellion/type/object/binding)
  package: rebellion

An object type binding is a type binding for an object type. Object type bindings contain compile-time information about the object type’s name and fields, as well as runtime bindings for its predicate, type descriptor, and other runtime components. To extract an object type binding bound by define-object-type, use the object-id syntax class.

procedure

(object-binding? v)  boolean?

  v : any/c
A predicate for object type bindings.

syntax class

object-id

A syntax class for object type bindings bound by define-object-type. This class matches any identifier bound with define-syntax to a value satisfying the object-binding? predicate, similar to the static syntax class. Upon a successful match, the object-id class defines the following attributes:

Examples:
(require (for-syntax rebellion/type/object/binding))
 
(define-simple-macro (object-accessors object:object-id)
  (list object.field-accessor ...))
 
(define-object-type folder (accumulator initial-state))

 

> (object-accessors folder)

'(#<procedure:folder-accumulator>

  #<procedure:folder-initial-state>

  #<procedure:folder-name>)

procedure

(object-binding-type binding)  object-type?

  binding : object-binding?
Returns the object type that binding is for. When an object type binding is bound with define-syntax, this can be used at compile-time to obtain information about the name and fields of the object type.

procedure

(object-binding-descriptor binding)  identifier?

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

procedure

(object-binding-predicate binding)  identifier?

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

procedure

(object-binding-constructor binding)  identifier?

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

procedure

(object-binding-accessor binding)  identifier?

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

procedure

(object-binding-fields binding)

  (vectorof identifier? #:immutable #t)
  binding : object-binding?
Returns a vector of the identifiers used for the fields of the object type bound by binding. This includes both the private fields and the name field.

procedure

(object-binding-field-accessors binding)

  (vectorof identifier? #:immutable #t)
  binding : object-binding?
Returns a vector of identifiers that are bound at runtime to the per-field accessors of the object type bound by binding. This includes accessors for both the private fields and the name field.

procedure

(object-binding-private-fields binding)

  (vectorof identifier? #:immutable #t)
  binding : object-binding?
Returns a vector of the identifiers used for the private fields of the object type bound by binding. Unlike object-binding-fields, this does not include the name field.

procedure

(object-binding-private-accessors binding)

  (vectorof identifier? #:immutable #t)
  binding : object-binding?
Returns a vector of identifiers that are bound at runtime to the per-field accessors of the object type bound by binding. Unlike object-binding-field-accessors, this does not include an accessor for the name field.

procedure

(object-binding-name-field binding)  identifier?

  binding : object-binding?
Returns an identifier for the name field of the object type bound by binding.

procedure

(object-binding-name-accessor binding)  identifier?

  binding : object-binding?
Returns an identifier that is bound at runtime to the accessor or the name field of the object type bound by binding.

2.7.4 Object Type Chaperones and Impersonators

procedure

(object-impersonate instance 
  descriptor 
  [#:properties properties 
  #:chaperone? chaperone?]) 
  (object-descriptor-predicate descriptor)
  instance : (object-descriptor-predicate descriptor)
  descriptor : initialized-object-descriptor?
  properties : (hash/c impersonator-property? any/c #:immutable #t)
   = empty-hash
  chaperone? : boolean? = #t
Returns an impersonator of instance with each impersonator property in properties attached to it. If chaperone? is true (the default), the returned impersonator is a chaperone.