2.4 Enum Types
(require rebellion/type/enum) | package: rebellion |
An enum type is a simple kind of data type made up of a small fixed set of named values. Enum types are useful for representing groups of related constants, such as primary colors and directions.
(define-enum-type direction (up down left right)) (define-tuple-type point (x y)) (define/contract (point-move pt dir amount) (-> point? direction? real? point?) (match-define (point x y) pt) (match dir [(== up) (point x (+ y amount))] [(== down) (point x (- y amount))] [(== left) (point (- x amount) y)] [(== right) (point (+ x amount) y)]))
> (point-move (point 2 2) up 5) (point 2 7)
> (point-move (point 1 4) left 10) (point -9 4)
> (point-move (point 1 4) 'up 5) point-move: contract violation
expected: direction?
given: 'up
in: the 2nd argument of
(-> point? direction? real? point?)
contract from: (function point-move)
blaming: top-level
(assuming the contract is correct)
at: eval:4:0
syntax
(define-enum-type id (constant-id ...) enum-option ...)
enum-option = #:omit-root-binding | #:descriptor-name descriptor-id | #:predicate-name predicate-id | #:discriminator-name discriminator-id | #:selector-name selector-id | #:property-maker prop-maker-expr | #:inspector inspector-expr
prop-maker-expr :
(-> uninitialized-enum-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 enum type and returns #f otherwise. Each constant-id is bound to a constant instance of the created enum type.
discriminator-id, which defaults to discriminator:id —
an enum discriminator that accepts instances of the enum type and returns the integer corresponding to that instance. selector-id, which defaults to selector:id —
an enum selector that accepts integers and returns the instance of the enum type corresponding to that integer. descriptor-id, which defaults to descriptor:id —
the type descriptor for the created type.
Additionally, unless #:omit-root-binding is specified, the original id is bound to an enum 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-enum-implementation for more information about these parameters.
(define-enum-type suit (diamonds clubs hearts spades)) (define-enum-type face (jack queen king)) (define-tuple-type card (type suit)) (define king-of-clubs (card king clubs))
> (card-type king-of-clubs) #<face:king>
> (card-suit king-of-clubs) #<suit:clubs>
(define/contract (card-value c) (-> card? (integer-in 1 13)) (match (card-type c) [(? number? x) x] [(== jack) 11] [(== queen) 12] [(== king) 13]))
> (card-value king-of-clubs) 13
> (card-value (card 7 spades)) 7
> (card-value (card jack hearts)) 11
provide transformer
(enum-out enum)
2.4.1 Enum Type Information
procedure
(enum-type? v) → boolean?
v : any/c
procedure
(enum-type name constants [ #:predicate-name predicate-name #:discriminator-name discriminator-name] #:selector-name selector-name) → enum-type? name : interned-symbol? constants : keyset? predicate-name : (or/c interned-symbol? #f) = #f discriminator-name : (or/c interned-symbol? #f) = #f selector-name : (or/c interned-symbol? #f)
> (enum-type 'weather (keyset #:sunny #:cloudy #:raining #:snowing))
(enum-type
'weather
(keyset #:cloudy #:raining #:snowing #:sunny)
'weather?
'discriminator:weather
'selector:weather)
procedure
(enum-type-name type) → interned-symbol?
type : enum-type?
procedure
(enum-type-constants type) → keyset?
type : enum-type?
procedure
(enum-type-predicate-name type) → interned-symbol?
type : enum-type?
procedure
type : enum-type?
procedure
(enum-type-selector-name type) → interned-symbol?
type : enum-type?
procedure
(enum-type-size type) → natural?
type : enum-type?
2.4.2 Enum Type Descriptors
Enum types are implemented by representing each constant in the enum with an integer. The type descriptor of an enum type has contains two functions for dynamically inspecting this mapping:
An enum discriminator function, which maps an enum constant to an integer.
An enum selector function, which returns the enum constant corresponding to a given integer.
These two functions are inverses of each other. Assuming the enum descriptor is initialized, these functions can be used to dynamically convert between integers and enum constants. To convert between strings or symbols and enum constants, use the integers in conjunction with enum-type-constants. Note that the constants of an enum type are stored in a keyset, so they are always in alphabetical order.
procedure
(enum-descriptor? v) → boolean?
v : any/c
procedure
v : any/c
procedure
v : any/c
procedure
(make-enum-implementation type [ #:inspector inspector #:property-maker prop-maker]) → initialized-enum-descriptor? type : enum-type? inspector : inspector? = (current-inspector)
prop-maker :
(-> uninitialized-enum-descriptor? (listof (cons/c struct-type-property? any/c))) = default-enum-properties
(define descriptor:weather (make-enum-implementation (enum-type 'weather (keyset #:sunny #:cloudy #:raining #:snowing)))) (define weather? (enum-descriptor-predicate descriptor:weather)) (define discriminator:weather (enum-descriptor-discriminator descriptor:weather)) (define selector:weather (enum-descriptor-selector descriptor:weather))
> (selector:weather 0) #<weather:cloudy>
> (selector:weather 1) #<weather:raining>
(define cloudy (selector:weather 0))
> (weather? cloudy) #t
> (discriminator:weather cloudy) 0
procedure
(enum-descriptor-type descriptor) → enum-type?
descriptor : enum-descriptor?
procedure
(enum-descriptor-predicate descriptor) → predicate/c
descriptor : enum-descriptor?
procedure
(enum-descriptor-selector descriptor)
→ (-> natural? (enum-descriptor-predicate descriptor)) descriptor : enum-descriptor?
procedure
(enum-descriptor-discriminator descriptor)
→ (-> (enum-descriptor-predicate descriptor) natural?) descriptor : enum-descriptor?
procedure
(default-enum-properties descriptor)
→ (listof (cons/c struct-type-property? any/c)) descriptor : enum-descriptor?
procedure
(default-enum-equal+hash descriptor) → equal+hash/c
descriptor : enum-descriptor?
procedure
(default-enum-custom-write descriptor)
→ custom-write-function/c descriptor : enum-descriptor?
procedure
(default-enum-object-name descriptor)
→ (or/c natural? (-> any/c any/c)) descriptor : enum-descriptor?
2.4.3 Enum Type Bindings
(require rebellion/type/enum/binding) | package: rebellion |
An enum type binding is a type binding for an enum type. Enum type bindings contain compile-time information about the enum type’s name and values, as well as runtime bindings for its predicate, type descriptor, and other runtime components. To extract an enum type binding bound by define-enum-type, use the enum-id syntax class.
procedure
(enum-binding? v) → boolean?
v : any/c
syntax class
type —
an attribute bound to a compile-time enum-type? value describing the type. binding —
an attribute bound to the compile-time enum-binding? value extracted from the matched identifier. name —
a pattern variable bound to the enum type’s name, as a quoted symbol. constant ... —
a pattern variable bound to the enum’s constants. constant-name ... —
a pattern variable bound to the names of the enum’s constants, as quoted symbols. predicate —
a pattern variable bound to the enum type’s runtime type predicate. discriminator —
a pattern variable bound to the enum type’s runtime enum discriminator. selector —
a pattern variable bound to the enum type’s runtime enum selector. descriptor —
a pattern variable bound to the enum type’s runtime type descriptor.
(require (for-syntax rebellion/type/enum/binding)) (define-simple-macro (enum-names enum:enum-id) (list enum.constant-name ...)) (define-enum-type compass-direction (north south east west))
> (enum-names compass-direction) '(east north south west)
procedure
(enum-binding-type binding) → enum-type?
binding : enum-binding?
procedure
(enum-binding-constants binding)
→ (vectorof identifier? #:immutable #t) binding : enum-binding?
procedure
(enum-binding-descriptor binding) → identifier?
binding : enum-binding?
procedure
(enum-binding-predicate binding) → identifier?
binding : enum-binding?
procedure
(enum-binding-selector binding) → identifier?
binding : enum-binding?
procedure
(enum-binding-discriminator binding) → identifier?
binding : enum-binding?