[R6RS] Records draft

Marc Feeley feeley
Tue Jun 21 21:35:07 EDT 2005


On 21-Jun-05, at 9:59 AM, Michael Sperber wrote:

>
> ... is at:
>
> http://www-pu.informatik.uni-tuebingen.de/users/sperber/srfi/record- 
> srfi.html
>

My first impression (more to follow) is that the syntax of the  
syntactic record definition form suffers from a bad case of  
parenthesitis.  It is just too verbose and has too many positional  
arguments that will be hard to remember.  Specifically:

1) I find the required "formals" part strange.  First of all, the  
formals
    should be right next to the constructor's name to highlight the  
link.  It
    should be optional to specify the formal parameters because very  
often they
    are the same as the field names, and the init expressions are  
typically
    the corresponding formal parameters.

2) The short form is (define-record-type name formals...) and the  
long form
    is (define-record-type (name constructor predicate) formals...).   
Why parens
    in the second case and not in the first?  Only because formals is  
a list and
    it would be ambiguous to put parens only around the constructor  
and predicate.
    This strange syntax is caused by using a positional-only approach  
to specifying
    the arguments of the define-record-type form.  The name should  
stand out and
    be separate from the rest, so all record definition forms should  
start with

          (define-record-type name ...)

3) Why is there a way to provide both the name of the constructor and  
the
    name of the predicate or neither, but not a way to provide one or  
the
    other?  Once again this is due to the positional-only approach.   
Moreover
    I can imagine a future extension of the record definition form where
    more than one constructor can be specified.  But such an  
extension will be
    hard to tack-on to the syntax proposed.  I must repeat what I  
have said
    before: a keyword-based syntax would be more appropriate for a  
case like
    this where there are several parameters and many have reasonable  
defaults.
    Here are some examples to give a feel of what a keyword based  
syntax would
    look like:

        keyword-based                  positional-based (as proposed)

    (define-record-type point     (define-record-type point (x y)
      x                             (fields ((mutable x) x)
      y)                                    ((mutable y) y)))

    (define-record-type point     (define-record-type (point make- 
point is-a-pt?)
      predicate: is-a-pt?                             (x y)
      (x immutable:)                (fields ((immutable x) x)
      y)                                    ((mutable y) y)))

    (define-record-type point     (define-record-type (point make-pt  
is-a-pt?)
      constructor: (make-pt a b)                      (a b)
      predicate: is-a-pt?           (fields ((immutable x) (+ a b))
      (x immutable: init: (+ a b))          ((mutable y) #f)))
      y)

    It is easy to add other field attributes with a keyword-based  
approach:

    (define-record-type bingo
      (foo foo-getter)                         ; field is immutable,  
SRFI-9 style
      (bar bar-getter bar-setter unprintable:) ; field not printed by  
"write"
      equality-skip:                           ; all the following  
fields are
                                               ; ignored by equal?
      (baz immutable:)
      qux)

    Note: I'm not proposing these particular field attributes (even if
    they are supported by Gambit).  I'm simply making the case for a
    syntax that is easy to extend in the future, or easier for
    implementations of Scheme to extend in an implementation
    specific way, such as the Gambit attributes.

4) The name "define-record-type" is too long for my taste, I prefer
    "define-record" or simply "define-type".  How sweet it would be to
    have lightweight (and easily understandable) code like this:

      (define-type point x y)

      (define (f lst) (map (lambda (z) (make-point z z)) lst))

    instead of the relatively heavyweight:

      (define-record-type point (x y) (fields ((mutable x) x)  
((mutable y) y)))

      (define (f lst) (map (lambda (z) (make-point z z)) lst))

5) Finally, I see no mention of "final" (non extensible) record  
types, and
    "abstract" record types (with no constructor).  I think record type
    definitions should be final by default (because it is the common  
case
    and can be compiled more efficiently), and have a keyword to  
indicate an
    extensible type, for example:

      (define-type point
        extensible:
        x
        y)

    An alternative, which I presented in Snowbird, is that the name of
    the record subtype definition form is specified in the record type
    definition (if it is not specified then the record type is not
    extensible).  For example:

     (define-type point                 ; this type is extensible
       extender: define-type-of-point
       x
       y)

     (define-type-of-point color-point  ; this subtype of point is  
not extensible
       color)

Marc



More information about the R6RS mailing list