[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