[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