why generative? Shiro Kawai 10 Mar 2009 10:29 UTC

This may be too late for discussion, but I just wonder why
make-rtd should be generative.  (I posted my question to
comp.lang.scheme a few days ago but it seems that the
newsgroup is very quiet recently?)

The reason I can think of is that we need a way to create a
distintive type.  But that can be achieved easiliy without
requiring make-rtd generative, as I describe later.

An alternative idea is to change definition of identity of
rtd.  What if we define two rtds are eqv? if they have the
same NAME, FIELDSPECS and eqv? PARENT?  (If we extend rtd to
have sealed and/or opaque flags, we compare those flags as
well).  In other words, we make make-rtd behave
functionally, meaning it returns eqv? objects for equivalent
set of arguments.

Since rtds are immutable, an implementation doesn't actually
need to compare their components to test type identity.  For
example, make-rtd can be memoizing and returns eq? rtd for
exactly the same arguments, or make-rtd calculates some kind
of "type signature" symbol from its arguments so that two
rtds can be compared by simply comparing them.  We can leave
actual optimization strategy to implementors.

In order to get distinctive types, we can add one more
member to rtd; let's say it uid.  It is an arbitrary Scheme
object and is compared by eq? when comparing two rtds.  Then
we can guarantee distinctive type by passing an object that
can't be eq? to other objects, such as (cons #f #f).

This scheme seems to have advantages over R6RS way when we
want non-generative behavior: (1) It makes bookkeeping of
rtd's identity implicit, as opposed to the explicit identity
specified by R6RS.  The R6RS way effectively introduces a
separate namespace for rtd, which doesn't seem to "fit" to
other parts of Scheme spec, at least to me.  (2) It
eliminates the need of something like UUID in some cases
for non-generative make-rtd.

Whether the higher-level syntactic layer should be
generative or not is another problem.  If programmers
generally expects distinctive types for every
define-record-type, then we can specify that it expands into
make-rtd with passing unique object to uid by default, with
optional syntax to give the uid.  Non-generative use case
such as efficient local record definition can just pass
something like #f to uid, and the compiler can recognize it
and generate efihficent code.   At worst, if you need local
record definition *with* distinct type, you can pass UUID uid,
which is no worse than R6RS.

Is there a flaw in this idea?  Are there any definitive
reason I'm not aware of that make-rtd should return a fresh
rtd by default?

--shiro