I also feel that there is one feature which we ought to remove from SRFI-9
of which I was not aware until recently re-examining the specification
closely. That's the filtering constructor syntax, which allows you to
define a constructor taking a limited number of fields instead of taking
all the fields. This has two problems for me: firstly, it presents a
problem where we have to deal with yet another case of identifier versus
symbolic equality; secondly, it is directly in the middle of functionality
such as to be useless to someone like myself.
While the first problem can be dealt with, the second problem is more
troublesome. Why would you want to change the constructor to take less
fields? Well, the only reason I have for doing this is if I want the
forward facing interface to only have a specific number of arguments, but
I want to store additional state in the record. If I do want to store
additional state in the record, I most certainly do not want to have an
unknown and unspecified value in there, so I am going to want to fill it
with something of my own choosing.
This makes the filtered constructor on SRFI-9 essentially useless. Since I
cannot control at the definition time how I fill in those other values, it
means that I am going to have to create another function that actually
does fill in the values. For example, consider a record that has a hidden
hashtable in it:
(make-stuff) => #<stuff>
(stuff-table #<stuff>) => #<hashtable>
Now, if I use SRFI-9, I'd like to do something like this:
(define-record-type stuff (make-stuff) stuff? (table stuff-table))
However, i cannot do this, and instead, the way that this is normally done
with SRFI-9 is something like this:
(define-record-type stuff (%make-stuff table) stuff? (table stuff-table))
(define (make-stuff) (%make-stuff (make-eq-hashtable)))
Now, in this case, the filtered constructor is useless. I could do
something like this:
(define-record-type stuff (%make-stuff) stuff? (table stuff-table
stuff-table-set!))
(define (make-stuff) (let ([res (%make-stuff)]) (stuff-table-set! res
(make-eq-hashtable)) res))
But there I have forced a field to be mutable when I really want it to be
immutable.
So, the only case where the filtered constructor is useful are in those
cases where you do not want to make an external procedure and you have
fields that you don't want to be part of the constructor interface but
that will not be populated until some other procedure runs, and that you
know will not be used or referenced before that populating procedure is
run.
That is a pretty specialized case for something that we no longer need.
Since we already have modules, there is no need for a filtered constructor
anymore. If we wanted something more sophisticated, we can get it, but
then we should do it so that we can control the interface sufficiently to
do what I might want to do above. For example, R6RS define-record-type
does let us do this, and other record syntaxes do as well:
(define-record-type stuff (fields table) (protocol (lambda (n) (lambda ()
(n (make-eq-hashtable))))))
Now, I'm not saying that WG1 should standardize any additional
functionality, because we have already clearly voted on that point, but I
just want to ask that we reconsider the *syntax* of our features.
Something like this would be much easier to extend and work with:
(define-disjoint-type (stuff make-stuff stuff?)
(fields (table stuff-table)))
This allows WG2 to use the same syntax with new clauses to extend the
functionality in meaningful ways, such as adding inheritance or a protocol
sort of functionality.
I'm sorry if I am beating an already decided horse, but I just really
think that this will come back to bite us.
Aaron W. Hsu
--
Programming is just another word for the lost art of thinking.
> So, as some of you know, I really dislike the syntax of SRFI-9 and
> SRFI-99. I can understand the desire to limit our features to SRFI-9,
> however. I do want to pose at least one question or plea (however
> you want to read it); can we please re-examine the syntax of SRFI-9
> before deciding to standardize on it?
The four WG1 members who commented on this issue all said that the main
virtue of SRFI 9 was backward compatibility. That's about the syntax as
well as the features.
> [...] very messy upwards path [...] ugly workarounds in SRFI-99 [...]
I don't think the (name parentName) convention for single inheritance
is ugly or messy. The rest of the SRFI 99 stuff is about having it
automatically generating names for you, which I consider a fairly
pointless feature. Adding additional features could be done in the
style of a property list:
(define-record-type foo
(make-foo x)
foo?
(x get-x)
foo foo-value
bar bar-value)
> This makes the filtered constructor on SRFI-9 essentially useless.
It's a matter of backward compatibility.
--
Even the best of friends cannot John Cowan
attend each others' funeral. co...@ccil.org
--Kehlog Albran, The Profit http://www.ccil.org/~cowan
> The four WG1 members who commented on this issue all said that the main
> virtue of SRFI 9 was backward compatibility. That's about the syntax as
> well as the features.
I think it rather arrogant of us if we close our eyes to see only SRFI-9,
when there is also R6RS' record system, which is also well used. We have
plenty of record systems out there; backwards compatibility with all of
them simply is not an option, and choosing the worst syntax to standardize
does not reflect well on our priorities.
The workarounds you describe for getting around the flaws in the SRFI-9
syntax are not used in any existing record system I have seen. Why are we
intentionally making things difficult? With a module system, having a
record system that is different than SRFI-9 poses absolutely no problems
with backwards compatibility, because someone can trivially provide a
module for SRFI-9.
If the only issue is that we have something of the same name, let's use a
different name. Otherwise, we're either going to stick WG2 with an awkward
record form, or WG2 will need to write their own version, and we'll have
two syntactic forms, plus other procedural forms, making the language much
less elegant and that much more complex, for no reason, and to no better
end concerning things like backwards compatibility.
On Mon, May 9, 2011 at 10:32 AM, Aaron W. Hsu <arc...@sacrideo.us> wrote:
> So, as some of you know, I really dislike the syntax of SRFI-9 and SRFI-99.
> I can understand the desire to limit our features to SRFI-9, however. I do
> want to pose at least one question or plea (however you want to read it);
> can we please re-examine the syntax of SRFI-9 before deciding to standardize
> on it?
In order to revisit something we've already decided on, I'd
like either
1) strong community interest in the issue
2) discovery of a significant new issue
at least until we've gone through all the other tickets. So
while I sympathize, reiterating your dislike for a decision is
not grounds for revisiting it.
> I also feel that there is one feature which we ought to remove from SRFI-9
> of which I was not aware until recently re-examining the specification
> closely. That's the filtering constructor syntax, which allows you to define
> a constructor taking a limited number of fields instead of taking all the
> fields. This has two problems for me: firstly, it presents a problem where
> we have to deal with yet another case of identifier versus symbolic
> equality; secondly, it is directly in the middle of functionality such as to
> be useless to someone like myself.
OK, now that argument wasn't brought up before :)
I'll re-open this ticket, and encourage members to
refine their proposals. The new default will be SRFI-9.
--
Alex