Full name (required): Aaron W. Hsu
Location (optional): Bloomington, IN
Affiliation (optional): Indiana University
Statement of interest: Not Required
Vote (required): yes
Rationale (optional):
All opinions expressed here are my personal opinions and independent of the fulfillment of my obligations as a member of either WG1 or WG2.
WG1’s efforts are far from perfect, reek of reactionary zealotry, and at times, make little to no sense. However, that being said, I very much doubt that anyone else would have come up with anything substantially better given the constraints under which we operated. Indeed, fundamentally, I believe that we could not have done better under these constraints, and I actually draw into question the validity of the constraints at all. Nonetheless, I care about Scheme, and I care about trying to help grow the language. As with R6RS, I believe the right move is to ratify and move on. In moving on, I believe the first step is to proceed to ignore some very important philosophical and technical expressions of WG1.
Firstly, I believe that we have made some very real, serious errors in the standard that we have created, and I believe that the community at large should explicitly condemn them and ignore them in the standard. These mistakes are technical, rather than philosophical in nature, and because they are easy to enumerate, I shall do this first, before proceeding to the more philosophical content of this rationale.
- The standard itself fails to scale well in a number of critical points. The first and most glaring of these is the record system. While the WG1 made the arguable decision of altering the R6RS module syntax in favor of “system” extensions [rant: the very idea of system extensions is anathema to Scheme and the Scheme Way], we doggedly held to demonstrably poor scalability of SRFI-9 records. The limited expressivity and power of the record system are understandable, given our constraints. What I do not understand is our refusal to use a syntax both successfully demonstrated as workable and successful in R6RS as well as fundamentally more scalable and open to clean extension. This makes no sense, given the trivially easy way in which this could have been addressed. The end result of this is that any real Scheme system worth its salt will included its own, proper record system, rather than extending the syntax of the standard one. This does absolutely nothing to move forward code sharing when very many real, sharable Scheme programs are written in ways that clash with SRFI-9 records.
- The standard has, as a whole, favored the introduction of new procedure names to handle new options for procedures that do effectively the same thing. In some cases this makes a bit of sense, as it would be unwieldy to do otherwise. However, there are other places where this does not make sense, and in particular, places where parameters, which we provide, could more readily be used. These places include procedures that provide behavior which is inherently dangerous and ought not to receive a full procedure name. The write procedures come to mind. The include and include-ci forms also come to mind. Adding more names doesn’t scale well, and I think we’ve gone wrong here. However, this failure is much more minor compared to records.
- There are places in the standard where we have fundamentally introduced gratuitous incompatibility with the R6RS standard “just because it’s R6RS.” An example is the error procedure. Here, there was no reason not to diverge from R6RS’ behavior, especially given that the R6RS behavior is a more expressive, useful form.
- While I understand and support to some degree the change of module syntax to favor a more extensible syntax, the way in which this was extended bothers me to some degree. This would include the include-{ci,library-declrations} forms, which feel ugly and unnecessary. Indeed, they are necessary largely because of the limitations on the way that we have treated modules, and I would have preferred to make modules extensible in the Scheme way, rather than the way that we have, but what we have is a compromise.
- I am very leery of the cond-expand form, and I believe that it also fails to scale well. We have done little to fix the issues in using and making cond-expand useful. We have also ignored fundamentally more flexible and useful forms.
In general, I believe that we could go on this way and continue to find other errors. Many of these errors are, I believe, the result of the WG trying to make something fundamentally useful without relying on WG2. This is a mistake. By requiring that we work in certain constraints (the lack of a full featured macro system, for instance) necessitates the use of sub-par constructs which are more complicated, the complication of which needed to exist only in the absence of more general, and more expressive forms. Contrary to the nature of simplicity and elegance, I believe that much of what WG1 has accomplished is to use patches on a self-constrained system, resulting in features piled on that could easily have been removed or more cleanly implemented in the presence of more general and expressive features. If WG2 could do it better with more expressive features, then why should WG1 duplicate features in a more ugly and less clean manner that does not scale as well just to have them? Rather, the correct approach would have been to allow implementations who wanted such features to use WG2 features that were designed. Unfortunately, we will likely now have a set of overlapping features implemented in WG2, and this doesn’t do anyone any favors.
Now, I’d like to make a comment at this point. The WG1, by this standard, would seem to have no conception of user extensibility. Indeed, IMO, the entire point of Scheme is that the user is as capable of language design as the systems implementer, and that, indeed, there is no distinction between the two but in name. The idea of their being system extensions and user extensions is a fundamentally anti-Scheme way of thinking. The Scheme language itself is supposed to allow the user to extend the system in powerful ways, and Scheme has been moving in this direction more and more. Real Scheme systems exist that allow the user to create their own workable library systems extensions, or to really do conditional expand-time expansion without requiring system extensions for feature symbols. All of this can be done programmatically and using no more than the constructs provided by R6RS. WG1 has introduced a dangerous precedent, IMO, to ignore these more elegant constructs in favor of fundamentally weaker ones coupled with special cased forms that could have easily been implemented at the user level in richer systems.
I believe much of this comes because the WG1 intentionally ignored the advances that have come in syntactic abstraction, while still attempting to come up with a self-contained and useful system.
That being said, I think we have made a lot of good trade-offs and a lot of good decisions along the way. We did not innovate the exception system, and I believe that the exception system being unified across platforms and especially, keeping the R6RS forms and semantics is a good move. It’s important because much of the work in this exception system has already been done and understood in R6RS systems. The forms are generally useful and helpful, but they are easy to understand and use. There are a number of cases where we decided to stick with R6RS, and IMO, these were all correct and good decisions. We have also made strides in providing more consistent mathematical operators and richer options there, which is a good thing. Many things have been tightened up and cleaned up.
On the other hand, we have, for some inexplicable reason, chosen to follow the wording and style of R5RS rather than the better, more precise, and clearer stylistic approach of the R6RS standard. I do not understand this except that it serves as a sort of reactionary statement against R6RS, which is not good. R6RS did a lot simply in standard organization and layout that we should have maintained, as well as with language, which we did not maintain. While we have incorporated a good deal of wording from R6RS, it would have been better to have started with R6RS as a base, rather than cherry picking from it. We have made strange decisions that simply don’t make much sense. For example, the choice to remain to the single unspecified value instead of an unspecified number of values.
And now for a bit of a personal rant. Scheme ought to be a systems and implementation language, as much as anything else. We should be using Scheme to implement Scheme. Moreover, Scheme should be powerful and expressive. Unfortunately, there seems to be a great deal of sentiment that drives standardization in Scheme that the standards should conform and coddle the least common denominator. All too often I hear, “That’s too much work to implement in a toy scheme,” as a good reason for not having a feature. Especially, for not having features that remove the need for having a handful of other features. We should be focused on making an useful, expressive language, rather than trying to bend over backwards to make the language easy to implement. If we really wanted to follow that line of reasoning, then we would not be using closures or any of the other language features that Scheme has introduced. Indeed, Scheme has often led the programming community in introducing features that others thought too hard to implement well. Well, Schemers then implemented them well, and the result was a language that was powerful and elegant and usable. The standard should be taking the intersection of high-quality, industrial strength implementations, not the intersection of very toy scheme ever written. That is not to say that toy schemes are not vitally important, but we need to get over this love of saying “This is a fully compliant Scheme!” for every toy scheme ever written. It’s perfectly okay for us to not expect toy schemes to be fully standards compliant. Research Schemes, too, need not be fully standards compliant. If we continue to hold on to the idea that our Scheme implementations should be easy to implement above more elegant programming constructs, then we are doomed. Scheme standards such as R5RS have, in the past, served as little else but the measure by which a toy scheme could enter into the fold, rather than serving as the useful programming standard by which real work was done. That should change. R7RS Small does little to change this world, and I think that’s a shame.
Scheme should be used for real work, and that means having real, useful, elegant, and simple constructs that are powerful and general, even if it chafes some Scheme implementers that they don’t have the time to implement all of those features. It’s okay. Not everyone deserves to be fully standards compliant.
Finally, I’ve ranted a while on what I don’t like and what I see as major issues and problems, but I’m still voting yes on ratification. That’s because this standard is substantially better than R5RS, and hopefully the misguided breaks from R6RS can just be ignored by the community. Those places where breaking from R6RS was justified should be few and small enough that all R6RS implementations can deal with them well. The conclusion of it all is that we won’t get anything better, and this is not really any worse than the R6RS effort, but I reiterate that it is in no ways superior to the R6RS effort either.
Maybe one day the community will see what a good thing it was to have syntax-case in a standard. Until then, we’ll trudge on with less powerful and less elegant constructs that hinder users and create an artificial divide between user and systems extender.