[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: propositions, oppositions, and some minor details

This page is part of the web mail archives of SRFI 57 from before July 7th, 2015. The new archives for SRFI 57 contain all messages, not just those from before July 7th, 2015.



Hi Taylor, let me try to answer your comments:

On Sun, 12 Sep 2004 campbell@xxxxxxxxxxxxxxxxxxxxxxxxxxx wrote:

First, my thoughts on the matter of syntactic details.  With respect to
compatibility with SRFI 9, I think it would just be easier if the
predicate were mandatory.  I don't see much of a reason to omit it,
and, by mandating it, it removes ambiguity: it clearly delimits the
type name & the constructor specifier from the fields.  Also, I don't
like the token for specifying mutability.  I think it would be better
to have a <field spec> nonterminal where the token for mutability is
_not_ a symbol; I think it would also be a bit more consistent to allow
a mutable field with an accessor but no separate modifier defined.
This replacement <field spec> nonterminal would fix both problems,
given some <mutability token>, e.g. #T/#F:

 <field spec> ->
     (<field label> [<accessor name>] [<mutability token>])
   | (<field label> <accessor name> <modifier name>)

How would you like the following (also proposed by Alex Shinn): Keep the SRFI-9 syntax mostly and just use #f for omitted elements, along with a couple of additional shortcuts:

 (define-record-type node (make-node left right) node?
                 (left  node-left  node-left-set!)
                 (right node-right node-right-set!))

Examples of variations:

 (define-record-type node make-node #f (left  node-left  #f)
                                       (right node-right #f))

   --> no predicate, default constructor arguments,
       both fields mutable but no setters defined

 (define-record-type node make-node #f (left #f #f) (right #f #f))

   --> as above, fields are mutable, but no getters or setters defined

 (define-record-type node make-node #f (left #f) (right #f))

   --> as above, but both fields immutable

 (define-record-type node make-node #f left right)

  --> shortcut for previous

 (define-record-type node #f #f left right)

  --> bare minimum if we have fields

 (define-record-type node make-node)
 (define-record-type node)

  --> adiitional shortcuts suggested by Felix if we have no fields

Mutability would depend, as in SRFI-9, on whether field clause is a two or three element list (or special case of atom as above).

The disadvantage would be all those little spiders walking across the screen when we want to leave things out, but maybe this design, because of its backward-compatibility, will please more people (in addition to being slightly more flexible) than my original.

The last syntactic detail that bothers me is the use of record types'
constructors in the pattern matching.  It would seem more sensical to
me to use the record type names themselves, not their constructors;
this would also solve the problem that required identifier macros --
which I am loathe to consider -- when defining the constructors so that
they could be used as regular variable bindings, bound to procedures,
as the specification specifies: they would no longer need syntactic
information used in pattern matching.

In accordance with the apparent majority opinion, I am pretty much decided on splitting pattern matching off (editors and the gods of time management willing), so this discussion should perhaps be left for then. I will just mention that with a more powerful macro system, one can keep a compile-time registry, obviating the need to bind constructor names as identifier macros. So it becomes a matter of taste whether one wants match expressions to look like the corresponding constructors or perhaps more like external representations or whatever. As you no doubt know, both styles of matchers exist for Scheme.

I also have a somewhat deeper semantic question: can SRFI 57 be used to
define subtypes of record types defined with SRFI 9?  My suggestion: an
emphatic *YES*.

I would agree.

I am also *vehemently* opposed to the completely unrestricted operator
of reflection RECORD->SEXP.  Reflection should either be completely
expurgated -- as I'd prefer --, or, if you intend to include any at all
in this SRFI, highly controlled by whomever defined the record type.
For example, Scheme48 has a simple, controlled mechanism for disclosing
the components of particular record types, though mostly for printing
unreadable objects.  I don't want to clutter this email describing it,
however, unless requested; request if you want me to.

Thanks, yes, I looked it up. I am not really happy either with record->sexp; on the other hand it may be better than nothing - something like it could be rather useful not just for generic printing but also other generic operations such as debugging (as Felix mentioned), generic unification algorithms over records, etc. Are you worried about data hiding? Of course the other side of the generic coin concerns generic construction of record values (e.g. reading), which I am reluctant to tackle in this SRFI because of its difficulty. I am open to more suggestions.

A smaller issue that I brought up on c.l.s seemed to have been left
unnoticed: record type equivalence seems to be based on name, not on
identity of the record type.  I believe this could be fixed by defining
an extra variable when invoking DEFINE-RECORD for a token identifying
the newly defined record type, and comparing against this, instead of
symbolic names, in BUILD-MAKER.

I prefer the simplicity of name equivalence. I know that with this interpretation, redefining a record type may break code that depends on the prior definition, but so may redefining a procedure or macro in standard Scheme.

Regarding implementations, it is obviously not tractable for many
Scheme implementations to implement DEFINE-RECORD as a syntax-rules
macro of such extreme proportions; although I find it amazing that you
wrote such a macro, I don't think it's practical, _especially_ not for
implementations that implement syntax-rules by translating the
expression into Scheme, compiling the Scheme, and then running that --
for _every_ use of syntax-rules.  I believe it would be a good idea to
provide an alternative implementation of DEFINE-RECORD in terms of even
a non-standard macro system, such as the fairly widely implemented
explicit renaming.*  It would also be undoubtedly easier to maintain as
the SRFI evolves than this gargantuan set of syntax-rules macros.

I agree. I actually started working on an alternative implementation in syntax-case but stopped for lack of time (as well as disgust at the non-uniformity of the available implementations, different methods of phase control, etc.)

Finally, it would also be good if an implementation were provided -- be
it in syntax-rules or explicit renaming or anything, as long as it can
be shown that it works -- that based records on the low-level record
interface used internally by SRFI 9's implementation, because that is
what most 'real' implementations will likely be based on.

I agree it could be good, but this would be somewhat on the back-burner as far as I'm concerned, I'm afraid. Closures can be rather efficient, especially once you start mixing pattern matching into the equation.

Regards
Andre