[R6RS] record constructor procedures

dyb at cs.indiana.edu dyb
Tue Aug 2 14:24:45 EDT 2005


The syntax we've proposed for specifying record-construction procedures
(1) satisfies my requirement that the child definition not need know
about parent field names and how to initialize them, and (2) covers the
majority of construction procedures one wants to write in my experience.
It is also (3) nice and simple.

As I mentioned before, there is a way to make constructor procedures
much more general while maintaining properties (1) and (2).  Here it
is:

Allowing the constructor to be specified as an clause:

  <clause> -> (constructor-procedure <constructor-expression>)

where <constructor-expression> must evaluate to a procedure.  When the
maker is invoked, it receives n+1 arguments, the additional (first)
argument being the base constructor p.  The procedure should invoke
p with the parent actuals, if any, and one value for each field as
follows, curried if there is a parent as shown below:

 (lambda (p x ...) (p <field-init ...)) ; no parent

 (lambda (p x ...) ((p <parent-arg> ...) <field-init> ...))

It's more general since we can build the procedure however we want
(e.g., by calling a maker-maker or by using rest interfaces or even using
case-lambda, optional arguments, or keyword arguments, if we have them),
and the maker itself can do all sorts of crazy things.  For example,
the maker can bind local variables and conditionally initialize groups
of fields:

 (lambda (p x y)
   (let ([q (f x y)])
     (if (> q 10)
         ((p q) y)
         ((p x) q))))

It can also do things with the record after it is created, e.g.:

 (lambda (p x y)
   (let ([r ((p x) y)])
     (register-record! r)
     r))

(This obviates the init expressions.)  It can even return something
other than a record instance or an unspecified value!

 (lambda (p x y)
   (let ([r ((p x) y)])
     (set! r* (cons r r*))
     (void)))

This may look potentially inefficient, but a decent inliner can eliminate
all of the extra lambdas and calls in the most common cases, since they
boil down to not much more than nested let expressions.

I implemented and used something like this a while back and it wasn't
too bad, but I rarely used the added generality and ended up with the
simpler but less flexible syntax upon which we based the proposal.

Kent


More information about the R6RS mailing list