[R6RS] Enumerations proposal pre-draft
Michael Sperber
sperber at informatik.uni-tuebingen.de
Sun May 7 10:58:57 EDT 2006
I've attached a new draft of the proposal, mainly for Will at this
point. The Subversion repo also contains a reference implementation.
This is sort of halfway between my original draft and Will's
counterproposal.
Highlights:
- Enumeration values are symbols.
- There's still a macro to set up enumeration types, and it's used to
define a convenience macro for expressing and statically checking
enumeration values.
- A bit more scaffolding is used to tie enumeration types and
enumeration-set types together; this enables using things other than
symbols as the basis for enumeration sets. (Such as the finite
types in Scheme 48.)
- Subtyping in enumeration-set types is enabled, as per Will's
proposal.
I tried to preserve the spirit of both. Let me know where I didn't
cut it.
--
Cheers =8-} Mike
Friede, Völkerverständigung und überhaupt blabla
Enumeration Types
=================
Enumeration types are subtypes of Scheme's standard symbol
types. Each enumeration type represents a fixed set of
symbols, which are specified when the enumeration type is
defined.
The syntax for defining an enumerated type is:
(define-enum-type <type-name>
<elements-name>
<predicate-name>
<index-accessor>
(<symbol> ...))
This defines a macro <type-name> and three procedures:
<elements-name>, <predicate-name>, and <index-accessor>. <elements-name>
will be a procedure of no arguments that returns symbols that comprise
the enumeration type, in the same order as they were specified.
<predicate-name> will take an arbitrary object, returning true if and
only if the object is one of the symbols returned by <type-name>.
<index-accessor> takes an arbitrary object, returning false if the
object is not one of the symbols returned by <type-name>; if the
object is one of the symbols returned by <type-name>, then
<index-accessor> returns its 0-origin index within the vector returned
by <type-name>.
<type-name> will be a macro of one operand, which must be one of the
enumeration symbols. It will return the corresponding symbol. If the
operand is not a symbol or if the symbol is not a member of the
enumeration type, an expansion-time exception will be raised.
The <type-name> procedure also serves as the canonical
representation of the enumerated type.
Example:
Example:
(define-enum-type color
colors
color?
color-index
(black white purple maroon))
(colors) => #(black white purple maroon)
(color? 'black) => #t
(color? 'gold) => #f
(color black) => 'black
(color purpel) => <expansion-time error>
(color-index (color purple)) => 2
Enumeration-Set Types
=====================
Enumeration-set types work naturally with the enumeration types.
The syntax for defining such a type is:
(define-enum-set-type <constructor-syntax> <constructor> <predicate>
<enum-type> <elements> <element-index>)
where <constructor-syntax> is an identifier that will be bound to a
constructor macro, <constructor> is an identifier that will be bound
to a constructor procedure, and <predicate> is an identifier that will
be bound to a predicate for the enumeration-set type being defined.
<enum-type>, <elements>, and <element-index> define the enumeration
type upon which the enumeration-set-type is based. <enum-type> must
be a macro corresponding to the <type-name> macro defined by
`define-enum-type', i.e. take a symbol operand and return the
corresponding enumeration member. <elements> must be a thunk
returning a vector of the elements of the enumeration, and
<element-index> must be a procedure accepting an enumeration element
and returning a corresponding index.
The <constructor-syntax> macro takes any number of symbol operands,
each of which must identify a member of the enumeration via the
<enum-type> macro. The <constructor> procedure will accept a list of
enumeration elements and return the corresponding enumeration set.
The <predicate> procedure will accept any object and return #t if the
object is an enumeration set of the type being defined, #f otherwise.
The representation of an enumeration set is not specified
by this proposal.
Given the enumerated type `color', for example, we can define
sets of color:
(define-enum-set-type color-set make-color-set color-set?
color colors color-index)
(color-set? (color-set black white)) => #t
(color-set? (make-color-set (list (color black) (color white)))) => #t
(color-set? '(black white)) => #f
(enum-set-universe enum-set)
(enum-set->list enum-set)
(enum-set-member? symbol enum-set)
(enum-set-subset? enum-set enum-set)
(enum-set=? enum-set enum-set) => boolean
(enum-set-union enum-set enum-set) => enum-set
(enum-set-intersection enum-set enum-set => enum-set
(enum-set-difference enum-set enum-set)
(enum-set-complement enum-set) => enum-set
`enum-set-universe' returns the thunk used in the position of
<elements> in the `define-enum-set-type' form; that thunk returns a
vector of the members of the enumeration type, in order.
`enum-set->list' returns a list of the symbols that belong to an
enumeration set.
`enum-set-member?' returns true if and only if its first argument is
an element of its second argument.
`enum-set-subset?' returns true if and only if the universe of its
first argument is a subset of the universe of its second argument
(considered as sets of symbols) and every element of its first
argument is a member of its second.
`enum-set=?' returns true if and only if its first argument is a
subset of its second and vice versa, as determined by the
enum-set-subset? procedure.
`enum-set-union' takes two enumeration sets that share the same
enumeration type as universe, and returns their union.
`enum-set-intersection' takes two enumeration sets that share the same
enumeration type as universe, and returns their intersection.
`enum-set-difference' takes two enumeration sets that share the same
enumeration type as universe, and returns their difference.
`enum-set-complement' takes an enumeration set and returns
its complement with respect to its universe.
((enum-set-universe (color-set))) => #(black white purple maroon)
(enum-set->list (color-set)) => ()
(color-set purpel) => <expansion-time error>
(enum-set-member? 'white (make-color-set '(white))) => #t
(enum-set-subset? (color-set white)
(enum-set-complement (color-set black))) => #t
(enum-set=? (color-set black maroon)
(enum-set-complement
(color-set white purple))) => #t
(define-enum-type other-color
other-colors
other-color?
other-color-index
(black white green red blue purple maroon))
(define-enum-set-type other-color-set make-other-color-set other-color-set?
other-color other-colors other-color-index)
(enum-set-subset? (color-set white) (other-color-set black white red green))
=> #t
(enum-set=? (color-set black white) (other-color-set black white))
=> #t
More information about the R6RS
mailing list