Proposal for a SRFI 240bis Daphne Preston-Kendal 22 Sep 2024 12:33 UTC

Principle: SRFI 9-compatible record type definitions should inherit exactly the properties of SRFI 9 record type definitions. Since SRFI 9 does not have inheritance nor an inspection layer, this means SRFI 9-compatible definitions are sealed and opaque by default.

The issues section of the SRFI says it wasn’t clear how to provide all the R6RS features in a SRFI 9-style definition while remaining ‘faithful’ to the SRFI 9 style. Here is a proposal.

Essential idea: adapt SRFI 99 to add syntactic support for specifying opaqueness and sealedness. We can also clean up the infelicities of SRFI 99 while we’re at it.
SRFI 99 extends the first subclause (‘<<type spec>> clause’) of SRFI 9 to make it possible to specify a parent record type: (<<type name>> <<parent>>)

This suggests a more general pattern of interpreting a <<type spec>> as a list of record types, left to right from subtype to supertype. So the natural place to put a specification of whether subtyping is allowed is here, before the <<type name>>:

<<type spec>> --> <<type name>> ; makes the type sealed
               |  (<<type name>> <<parents>>) ; also sealed
               |  (<<sealing spec>> <<type name>> <<parents>>) ; maybe sealed

<<sealing spec>> --> #t ; allow subtypes, i.e. non-sealed
                  |  #f ; explicitly don't allow subtypes, i.e. sealed

For controlling opaqueness, one can interpret non-opaque record types as all being a subtype of a universal record type called ‘record’. Continuing the pattern, a non-opaque record type explicitly names ‘record’ as one of its parents. We can take this opportunity to tighten up SRFI 99 by ensuring that a record type knows what all its parents are: note I have called the spec <<parents>>, not <<parent>>:

<<parents>> --> <<parent>> <<ancestor>> ... ; opaque
             |  <<parent>> <<ancestor>> ... record ; non-opaque

<<parent>> --> <<expression>>
<<ancestor>> --> <<expression>>

(‘record’ stands for an element in the list which is free-identifier=? to the record name of the universal record type.)

You have to name all of the <<parent>>’s ancestors in the list, except ‘record’ which only controls the opaqueness of *this* record type. If the <<parent>>’s ancestors are different, an assertion violation is signalled. There is no corresponding restriction in R6RS style, but this is necessary because of SRFI 99’s insistence that you name all the fields of your parents again.

Apropos of which, we can now relax the requirement of SRFI 99 that the names of fields of children have to be the same as the names of the fields of their parents. There only have to be the same number. That eliminates the symbol vs. identifier controversy in the same way R6RS did.

There are some problems with this proposal that are probably obvious. I’m not entirely happy with the proposal for controlling opaqueness in particular.

As a side note, 240bis (if it happens) should specify more clearly how to implement disambiguation between the two forms.
Specifically, if the use of d-r-t matches the syntax-case pattern (_ _ _ pred-name _ …) and the fender (identifier? #'pred-name), it’s a SRFI 9-style definition. Otherwise an R6RS-style one. This, and making SRFI 9-style definitions opaque and sealed by default, are the only changes I’d *definitely* make in a 240bis, even if there’s no way to control the opaque and sealed properties.

Daphne