Here are the preliminary results of the ratification vote.
As explained in the ratification procedure:
After the poll closes, the complete list of votes will be published on www.r6rs.org. This list will identify who voted, how they voted, and their explanations. This publication will be advertised to the public. Voters should check that their votes appear on the list as they intended. Any irregularities (missing votes, fraudulent votes, etc.) should be brought to the attention of the Steering Committee, who will take appropriate action.
The official results will be announced on August 26th. At that time we will also make available a companion document containing additional correspondence (late ballots or whatever) received after the poll closed.
Voting in favor of ratification:
Voting against ratification:
The language is described and explained very well.
Let me begin this addendum to my vote with thanks to the editors of the report, and everyone involved in the Scheme standardization process. I imagine it must have been a monumental effort, and I appreciate the work put into this wonderful programming language that I like so much. On reading the report and associated documents, and pondering what they contained and did not contain, I ultimately reached a position I expect to be isomorphic to that of all those who vote to ratify the proposal --- 'This putative standard is not perfect, but it is enough of an improvement over the previous state of affairs that it deserves to be ratified.' I have, on reflection, found that all of the imperfections that troubled me are solvable with standard-consistent SRFIs (which admittedly are not necessarily implementable portably) and support from the programming environment. Nevertheless, I feel that two of these imperfections deserve description here, perhaps as fodder for additions to the Rationale document, and perhaps to stimulate the production of said SRFIs. One of the imperfections that troubled me is the apparent inflexibility of the library system. It appears that it is difficult to define and use a library for, say, generic arithmetic, that would extend + and * to work on, say, matrices. Specifically, it appears that if one were to just import (rnrs (6)) and (generic-arithmetic), one would get a symbol conflict and one's program would not run. Consequently, one must explicitly exclude or rename the (rnrs (6)) symbols that are also exported by the putative (generic-arithmetic) library. One is forced to choose whether to exclude all the symbols that (generic-arithmetic) redefines or only to import those symbols from (generic-arithmetic) that one wants, and exclude only them. Both options are unfortunate. Excluding all (generic-arithmetic) symbols from one's (rnrs (6)) import is annoying, especially in the situation where (generic-arithmetic) exports many symbols, such as cos or expt, many of which one might not care about, and which one might need to seek out in the library's documentation. Doing so is also unstable if the (generic-arithmetic) library is updated to overwrite more (or fewer!) symbols from (rnrs (6)). On the other hand, importing only the symbols one wants from (generic-arithmetic) is also annoying, because it is difficult to remember all the operations one may wish to use, because one has to mention them in both the exclude and the import only clauses, and of course because one will then change one's mind about which exports of (generic-arithmetic) one wants. I have high hopes, however, that either a SRFI that extends the library import syntax with a shadow form and/or a clever M-x organize-imports function will alleviate this trouble. The other imperfection that troubled me is the absence of a facility analagous to Common Lisp's reader macros, and even an apparent obstacle to the definition of such a facility. I have several specific use cases for such a facility in mind, mostly to do with literal strings and regular expressions. Regular expressions, for better or for worse, use the backslash as an escape character just like strings do, but with a different set of escapable characters. If one tries to write literal regular expressions in Scheme, therefore, one is forced to double those of one's backslashes that are intended for the regular expression parser rather than the string parser. Furthermore, the natural printed representations of regular expressions will include backslashes, and are therefore grossly unsuitable for copying and pasting into Scheme source. All this is irritating in the extreme, and I wish Scheme had a mechanism whereby I could write a user-land library that permitted something like #/foo|bar/ as literal syntax for a regular expression (in this case, one that matched either 'foo' or 'bar'). In the particular case of regular expressions, a macro won't have the desired effect, because the string out of which one would build a regular expression gets read by the reader, with the attendant substitution of backslash escapes, before the macro-expander sees it. [Note that while I am all for an s-expression language for semantically specifying complex regular expressions, the compact, string-based notation is, in my experience, far easier to read for short, simple ones.] Another use-case for reader macros would be a facility analagous to Ruby's and Perl's string substitution mechanisms. I would like to be able to write what amounts to quasiquote for strings, and while the bulk of the work can certainly be done by a macro, it would be nice to have a short cut analagous to the backquote, perhaps sharpsign doublequote, for all of the same reasons. Yet another use-case for reader macros are here documents, again inspired by Perl and Ruby. Those languages provide a facility for embedding comparatively long documents into one's source code as string literals. Long literal strings have different needs from short ones, for instance in that the usual string delimiter characters may appear in them. Therefore, the here document facilities I am familiar with give the programmer control over the end delimiter used (often the word END or HERE on a line by itself, hence the name of the facility) and some control over the amount of string interpolation that is done on such embedded texts. Scheme could benefit from a library for this, and it seems that such a facility cannot be implemented as a macro over data that has already been processed by the reader. I have made the case that there are extensions to Scheme's lexical syntax that are worth considering adding to the language. They are sufficiently disparate and special-purpose that it would be aesthetically displeasing, to say the least, to implement them all as separate, one-off additions to the syntax of the language. They are also complex enough that it would be very valuable to be able to implement them as user libraries and actually experiment with how well they work, without having to recompile one's Scheme, before submitting SRFIs proposing specific variations to the larger community. In fact, it would be valuable to be able to use such extensions in one's own work, portably across implementations, without having to secure the community's consensus at all. I am therefore troubled by the paragraph immediately preceding Section 4.1 of the main report, which appears to throw up an obstacle to the implementation of reader macros or any analagous facility as a SRFI, in the form of a prohibition against any changes of the lexical syntax of Scheme whatever. One reading of that paragraph suggests that that impression may be mistaken, as a SRFI that introduced a shebang directive like #!srfi-314-reader-macros which signalled that subsequent code was subject to interpretation according to the reader macro facility specified in this hypothetical SRFI 314 would constitute a standard-compliant extension adding reader macros, but such a directive feels like an awkward increase in boilerplate, and begins to smack of a thrid-party code distribution mechanism completely orthogonal to the library system. Whether or not that reading of the report is, in fact, the intended one, I would greatly appreciate a rewording of the relevant segments to make that clearer, as well as a section of the Rationale document explaining why the editors of the report reached the decision that they did about reader macros.
I think the draft is a good continuation of the current standard. In particular, I like the newly introduced concept of libraries, that the handling of unicode characters is specified and that error conditions can be handled within a Scheme program in a standardized way.
I am an idiot for not replacing this text.
While there are some aspects of R5.97RS that I'm uncomfortable with, I think it's an overall step in the right direction. I'm confident that time will tell which aspects of the report need to be corrected, and that this will be done for R7RS.
I am voting 'Yes' for ratification of the current R6RS draft. My belief is that the draft represents a step forward for Scheme and that it accomplishes stated goals of the editors like unicode support, libraries and exceptions. In addition, I wrote in my registration statement that one of the criteria by which we should judge this standard is whether it provides clear direction on how to accomplish basic programming tasks in a way that does not require building your own infrastructure, or resorting to implementation-specific features. I believe that the current draft standard does an acceptable job meeting this criteria by providing standard mechanisms for things like exceptions and tagged records. I would like the thank the editors for their hard work and dedication in bringing the standard to its current state.
I confess that I didn't follow the development process of R6RS closely, but I have spent considerable time over the last few weeks reading the report and the various email trails carefully. I started out feeling pretty negative about the report. I really liked the 50-page tight simplicity of R5RS. But I've made my peace with most of R6RS. I do appreciate that there are a number of things that are specified in much greater detail, and/or better explained, and/or made more consistent. And while I'm not sure of the need for *all* the macro facilities, I'm willing to believe that they were felt necessary by people with more expertise in this area than me. A few minor observations: The terms *static* and *dynamic* scoping are used, and perhaps it can be assumed that the reader of this report would know what they mean. But it couldn't hurt, for instance, when explaining how a lambda expression evaluates to a procedure, that the particular method of evaluation implements static scoping. The term *deprecated* is used twice in the report, and twice in the rationale, but as far as I can see, is never defined. And I think in addition, that some justification should be given for the deprecation of features. I'm particularly concerned about force and delay, but the point is general. Some answers are hinted at near the end of the rationale document, in a very terse fashion, and force and delay aren't dealt with at all. I don't understand the way the base library functions in the report. In particular, I don't see why the base library isn't just part of the language. I mean, you don't have much of a language without arithmetic, for example, right? Why does a program need to explicitly import it? (Or did I miss something?) I know that in general, there is no definitive answer to why something gets in a language report. The ultimate answer simply is that the vote went that way. Nevertheless, I think the time may be right for an expository piece -- perhaps even a short book -- that attempts to justify the current definition of the language. Another obvious question, for instance, is this: Since call/cc has always been regarded largely as the Scheme escape mechanism, why was a new escape mechanism introduced in addition? And does this now do away with the need for call/cc? (I assume the answer is no, and I think I could even come up with a reason myself, but I'd like to see some discussion of this. It would at least be interesting, I think.) Maybe the answers to all these questions are available in the report or the email trail. But I'll bet that if I missed them, then a lot of other people did, or will, as well.
I find the current draft to be an excellent compromise. Building a standard that is acceptable to the community as a whole, especially one as opinionated as the Scheme community, is clearly going to make no one completely happy. However, R5.97RS contains all of the elements that I feel the new standard needs, perhaps not in exactly the same form as I would have specified them, but definitely in a form that should be acceptable to any implementer. Therefore I am voting TO RATIFY this draft of R6RS.
R6RS is a huge step forward. May its fulfillment match its promise.
The 5.97 draft standard brings Scheme up-to-date, helping to make it a viable alternative to more popular languages such as Java and Python. It library feature promises to facilitate a much larger body of portable Scheme code. And although these languages are improving, by borrowing ideas from Scheme and other functional languages, they still sorely lack features of Scheme which are important for my work, such as s-expressions and macros, which are incredibly useful for implementing domain specific languages. I understand that 5.97 may not be perfect from an academic point of view, but Scheme standards are living documents. The SRFI process and future versions of the Revised Report provide procedures for continuing to improve the standard. And Scheme implementors are surely free to make non-standard improvements and extensions, as they have in the past.
R5.97RS is a reasonable candidate. Ratifying it now is better than wait and quibble about details for an indefinite time. There is no doubt that this report has numerous advantages over R5RS and implementations should support it as soon as possible.
Reading through all of the electorates stated concerns makes me feel nostalgic; thinking back to that moment I first fell in love with computer science. Scheme seems to have that effect on people; love at first sight. Having read once that 'any truly good language, no matter what its original goals, will eventually become a general purpose programming language; that is the nature of a good language', I can't help but think that Scheme has this nature. Scheme is special. It draws people in. It is a place to learn, and play. My hope is that the direction set forth by R6RS will prepare Scheme for the masses, giving it an opportunity truly shine.
The proposed standard is an enormous improvement in my opinion. It makes the language much more complete and easier to use for various tasks. Most importantly, it will allow practical support for the language to grow rapidly. I would not be surprised if the proposed standard, if accepted, turns out to be a major breakthrough for the language.
No comments
I think that this version (5.97) is good progress to a better standard of Scheme, the basic ideas---lexical scoping, continuations, ...---being still present. Concerning the language itself, I especially appreciate: ---the notion of libraries, ---the way the standard libraries have been built, ---the definition of exceptions. My regrets: ---some functionalities related to handling files and directories are missing, ---the functions dealing with Unicode could have been more powerful. About the report, I appreciate the clear distinction among must/must not/should/shoud not/may. To conclude with a personal touch, I would be ready to rewrite MlBibTeX---my new implementation of the BibTeX program---using this new version.
I vote yes, not because I think R5.97RS is perfect, or because I agree with every detail of it, but because I think it is good enough to become the next generation of Scheme. See my registration for further explanations. R5.97RS is a compromise, and a well-crafted compromise is in my opinion the most sacred thing that a secular age knows.
Almost all of the proposed changes increase Scheme's usability more than they reduce its simplicity and elegance, even for novice programmers.
Scheme needs facilities for portable development.
I believe that R6RS will unite the Scheme community and reduce incompatibility between implementations.
Other people express their opinions so good that I will refer to them. Essay of Matthew Flatt says it all about a process of standartization: polishing current document will take lots of time and will add very little, we can wait for perfection forever. Let's make a milestone and see what will happen next. Developers of Scheme implementations who will like the result will soon make their products to be standard-compliant, others will stay with old standards, so we will clearly see how popular new standard will be. Previous standards also had some missing parts, which were added by subsequent standards, and had some unnesessary parts, removed by subsequent standards. Regarding a direction where Scheme standard is going, I will refer to essay of John Clements who calls for unity in areas which are no longer experimental field, but practical nesessity.
I've looked over the 5.97 draft and read the criticism that it includes too much. However, I disagree. While simplicity has always been one of the hallmarks of Scheme, the extremely small core language makes fragmentation between implementations inevitable. I believe that a more thorough standard is required to ensure potability.
The current 5.97 draft standard represents a reasonable consensus among the Scheme community and will serve well as the basis for future evolution of the language.
Although not perfect and still containing many areas that can be improved (as seen in the electronic discussion), I vote for approval. What we have here is a solid basis from which we can continue to guide the evolution of the Scheme standard. I see R6RS not as having reached the end goal, but as a step in the devlopement process. I thank the members of the committee for their time and effort.
The library system is an incredible step forward. It brings us closer to being able to write large systems that are portable across multiple implementations.
R6RS is "perfect".
Progress before perfection
I wanted to vote against ratification because some aspects of the standard are less than perfect. It's the tension between "the right thing" vs. "worse is better". This time Scheme needs a splash of "worse is better" to move the language standard forward. Let's hope some experience can help the next standards group reach for the right thing.
It's not perfect, but it's good enough, and I'm happy to leave pursuit of perfection to the r7rs editors.
A more extensive standard will make it easier to convince colleagues to use it.
Reason for voting yes: pragmatism. If I am to continue to write Scheme code, I must be able to make use of multiple implementations without bending over backwards to do so.
The current draft is not perfect, but it is a clear improvement on R5RS and takes Scheme forward in the correct direction.
It is time for Scheme to move forward.
Well, it's not terribly clever of me but I will steal a quote that J.H. Conway uses in the preface to 'On Numbers and Games' from Bunyan's 'Apology for his Book (Pilgrim's Progress): Some said 'John, print it'; others said 'Not so.' Some said 'It might do good'; others said 'No.' It will be a waste of time to drag out discussion of the draft much longer and, even for all the objections raised, 'it might do good.' Meanwhile, if there is long-term substance to the dissent, I am hopeful that that that dissent can gracefully congeal in and exploit the SRFI process to evolve things beyond the current draft. If it seems I'm saying 'Sigh. It'll do I guess. Good enough,' well, I suppose I am. That's not feint praise, though -- not for R_RS.
I no longer feel strongly enough about the case-sensitivity issue to throw a monkey-wrench into the whole ratification process. Besides, with Unicode being allowed as <constituent>s of <identifier>s, the case mapping would get complicated. If it was only <letter>s that were at issue, then it would expose a certain 'Roman' bias in the language. After all, it is easy to imagine someone having a good reason for an upper-case Greek letter being destinct from its lower-case counterpart.
greater compatibility between implementations
I would gladly trade a report full of mistakes---not that I think this is such a report, but some do---for a library system which properly handles hygienic macros. Therefore, I am voting "Yes" on R6RS. (The exception specification is just icing on the cake, as far as I'm concerned.) Some consolation for those who do think this report is full of mistakes: 1. I expect we'll be seeing lots of "(r6rs base)"-compliant implementations which leave off libraries they don't like, and 2. "...in most matters it is more important that the applicable rule of law be settled than that it be settled right." --- Burnet v. Coronado Oil & Gas Co., 285 U.S. 393, 406--408 (1932) (Justice Brandeis dissenting).
There are a number of good, nice things that I see being made available in this draft at a high level, and I greatly applaud the efforts of the committee to develop something that fosters the important goals of portability and simplicity. However, if I were to sum up my objections to ratifying this current draft, it would simply be that this draft no longer maintains what I have come to believe to be the core philosophical values of the Scheme language. This draft appears to diverge so significantly from the other drafts in terms of organization, size, and scope, that it seems like it should not even be considered the same species. While I cannot call myself qualified enough to discuss the minute details of language specification and detail, I can come at this from an user who has utilized Scheme for pedagogical, professional, and research uses. If the language fails to be able to provide for these three sectors, it fails to adequately serve its purpose. I believe that the standard falls short of meeting what I would consider essential advantages of Scheme in all three of these areas. It appears as though this standard attempts to bring in the ideas or concepts of other languages in an attempt to convert the language from a Beautiful Lisp language, to just another common programming language with some cool features and a strange syntax. That is to say, the focus seems to have been lost. Let me first deal with the pedagogical area. This draft removes the aspects of elegant simplicity and limited scope that make Scheme such a great language for teaching. Right now, Scheme is easy to learn, because the core concepts are simple, and they extend outward in reasonable, predictable ways. A student who is learning to program can focus on a small aspect of the language and feel comfortable with tackling the rest of it later. As I see it now, the standard has become massive relative to R5RS. Not only does its size hinder a new student, but it also makes creating simple conforming Schemes that are easy for a newcomer to learn impossible. Now, I do teach, but more pressing on my needs are research and professional development. I see severe limitations of the language with regards to professional development. Something that was great about using Scheme for professional development was that I could precisely mold my implementation and code to fit the task at hand precisely, rather than using large, sledge hammer tactics, such as is often the case with over engineered OO designs. Many of these features included in this draft are absolutely useful features that I like to have in an implementation. However, to require them in the standard limits the capacity of the implementors to work in small, specialized fields. Embedded devices immediately come to mind, but other things also come to mind, such as applications that may not desire unicode, libraries, or other pieces. Granted, I do believe in the goals of interoperability, which is one of the most problematic issues with Scheme's. I am not happy with the way the library, unicode, disregard for very standard SRFI's, such as SRFI-1. There does not seem to be enough flexibility given to the implementors to do things in ways that might suit particular applications. Put simply, the goal of interoperability should not be achieved by demanding that one size fits all. Rather, there should be discovered some way to simplify, rather than add on features, and to reduce the total bloat in a way that permits such bloat as extensions if desirable, but allows this to be done in a way so that applications may have confidence of running unmodified on other implementations assuming that the needed extensions exist. Rather, this standard assumes that features exist, and hopes to provide portability in this way. I do not like this. While I would love to see the features outlined here in implementations, I also wish to respect the flexibility of the language to permit specialized and very minimal implementations, without having to break with the standard. Now I'd like to come to one of my own personal rants. Case-sensitivity. The change to case sensitivity flies in the face of Scheme tradition, for little to no benefit. To suggest such a major change in the standard, imo, for absolutely no significant benefit, against the traditions of Scheme, seems to be very, very ugly. Besides the fact that its easier to add Case-sensitivity in than to remove it in individual implementations, I very much dislike this new addition, and take it as my example that this standard is trying to change the heart of Scheme. Thus, therefore, No.
As many other schemers I think that what makes Scheme great is its reduction to the strict minimum. I must agree that nowadays, a language that does not handle UTF-8, should it be in strings or identifiers, irritates me quite a bit. I also believe that a language that clearly lacks a module/library/embedded-regexps system often ends up being a real pain to use. And I am not the only one to reimplement FOLD-LEFT or FILTER more than once a day. Of course, there are some SRFI's out there supposed to make our lives easier. And I believe in that. In fact, I believe a lot more in time spent developping new SRFIs, than in time spent wondering about the best character set. For this reason, although I agree more than I disagree with the R6RS draft, I decided to vote 'No'. I personnaly stick more to R4RS than even R5RS (for I like plain old dirty DEFINE-MACRO and its lack of hygiene), and I see no point in supporting R6RS. Moreover, I reckon that it will make Scheme too much complicated for a gain not worth it. I suggest well all focus on defining vital SRFIs, and that we all agree on portable extensions of Scheme, to implement, say, TCP/IP, non blocking IOs or bindings to a graphical library. I think that it costs too much to add a module system, and that this should be left to the maintainer of implementations to give their own if they want. Yet, whatever system they use (shoud it even be built-in or 'built-over' as Snow), we should agree on definining and sharing APIs for just anything we find useful. Eventually, I decided to say No to R6RS, not because I think its fundamentally bad, but because I think that it is definitely not what we should be focusing on. Think of it as an 'I say no for your own good'. I hope that the community will always be open and eager to share and compare opinions, as it is now, and that the next major evolution of our langage will not rely on its already genetically well fitted design, but rather on its ease of use for whatever challenging task we encounter. And that sockets will be implemented eventhough no generic portable implementation could be given. In fact, I see Scheme as someone with a psychic disorder. We have a well defined language, we can think with it. But we spent (and still spend) so much time in defining the language itself that we eventually forgot to define the way to speak and communicate with the outside world. And R6RS does not solve this issue, neither does it offer the tools to solve it. Let's keep Scheme small, but let's add some new plugs to it. (No Scheme implementation was hurt during the redaction of this ballot. And the camel was already dead, I swear.)
1. Prolog ========= The candidate R6RS has been prepared over several years by a distinguished group of editors. They have worked hard to identify and solve problems in the R5RS to make Scheme a more useful language while remaining faithful to its origins. In particular, they have engaged in a public discussion of various drafts over most of the last year. We are indebted to the editors. 2. Vote ======= With regret, I vote to REJECT the candidate R6RS. 3. Reasons For Rejection ======================== The steering committee requires that votes to reject the candidate be accompanied by an explanation. My five reasons are given in this section. 3.1. Implicit mantissa widths ----------------------------- Section 4.2.8 of the candidate R6RS requires If x is an external representation of an inexact real number object that contains no vertical bar, then its numerical value should be computed as though it had a mantissa width of 53 or more. Such implicit mantissa widths have not been justified in the rationale or in discussions on the r6rs-discuss mailing list. It is not clear what problem they solve. The use of 'should' indicates that this is a recommendation. As such, this does nothing to solve problems of incompatibilities between implementations. On the other hand, it is simultaneously harmless and dangerous. Harmless because the 'or more' implies that the value might be calculated in infinite precision (i.e., exactly) and dangerous because it permits double rounding (e.g., if the implementation would represent the result using an IEEE double-precision format and the value is subnormal or if the implementation would represent the result using an IEEE single-precision format). 3.2 No Rounding Mode for Mantissa Widths ---------------------------------------- The candidate R6RS does not specify whether 0.75|1 should round to 0.5 or 1.0. This makes the mantissa widths unportable between implementations. 3.3 Explicit Mantissa Widths ---------------------------- Two reasons have been given for including explicit mantissa widths. Will Clinger [1] stated: The |p notation is a replacement for the # notation that the R5RS used for nonsignificant digits. One of the things we learned from this process is that many Scheme programmers, perhaps even a majority, and apparently including several implementors, were interpreting # to mean 5 rather than 0. That doesn't work, because it makes the numerical value depend upon the number of trailing #s, which are supposed to be insignificant. We also learned that hardly anyone is using the R5RS notation. Mike Sperber [2] stated: The way we have it now (I hope) at least gives implementations a chance to exactly represent binary floating-point numbers on output in external representations. I note that these justifications are in apparent conflict. One suggests that the |p notation is supposed to be an indicator of less precision and the other suggests that the same notation is supposed to be an indicator of a more precision. I would suggest that the |p notation goes against the guiding principle that 'programming languages should be designed not by piling feature on top of feature, but by removing the weaknesses and restrictions that make additional features appear necessary.' I would suggest: Continuing to use # to indicate imprecision, but tightening up the definition so that it is clear that it is to be interpreted as 0 and not 5. Alternatively, since 'hardly anyone is using' this notation, eliminate it. Extend the lexical syntax of inexact numbers to allow mantissas to be read and written in binary, octal, decimal, and hexadecimal. (An ambiguity in the syntax for non-decimals could be required by requiring a point at the end of the number or immediately before the exponent so, #x0e0 is an exact integer not an inexact zero whereas #x0. and #x0.e0 are inexact zeros.) The number->string procedure should also be extended to allow for non-decimal radixes for inexact numbers. 3.4 Records ----------- Andre van Tonder [3] and Will Clinger [4] have pointed out an incompatibility between the procedural and syntactic record layers. I would like to see this issue discussed and, if possible, solved. 3.5 Library Versions -------------------- I am completely unconvinced by the need to embed library versions in import specifications. I might support a means to label libraries with versions and to make that information available to importing programs or libraries at run-time (e.g., so they can abort if version X.Y of a certain library is imported). However, in general I believe that matching library versions should be solved outside of the language. 4 Other Issues ============== In this section I describe two issues which in themselves are not reasons to reject the candidate R6RS, but which I find very uncomfortable. 4.1 No Characters Beyond Unicode -------------------------------- Tom Lord [5] and John Cowan [6] have suggested that implementations be allowed to support characters beyond Unicode. I support this suggestion. 4.2 Inappropriate Syntax ------------------------ I am uncomfortable with the implementation of file-options, buffer-mode, etc., as syntax rather than procedure. [1] http://lists.r6rs.org/pipermail/r6rs-discuss/2007-June/003049.html [2] Private email. [3] http://lists.r6rs.org/pipermail/r6rs-discuss/2007-July/003080.html [4] http://lists.r6rs.org/pipermail/r6rs-discuss/2007-June/002825.html [5] http://lists.r6rs.org/pipermail/r6rs-discuss/2007-June/002863.html [6] http://lists.r6rs.org/pipermail/r6rs-discuss/2007-June/002878.html
'Programming languages should be designed not by piling feature on top of feature, but by removing the weaknesses and restrictions that make additional features appear necessary.' This is the first sentence in the introduction to RnRS for a reason. It is the heart of what Scheme is - a powerful general purpose programming language expressed with just a few primitives. As with any other good idea, it can be taken to an absurd extreme, and there's more than a little room for leeway in its interpretation, but the R6RS draft is so far removed from the idea that it destroys the whole spirit of the language. To be clear, I don't mind the large report, and am in fact happy that a large selection of standard libraries was included. What I object to is the fact that these libraries are not built on simple primitives, but many of them are in fact incompatible extensions to the language, and features which imply core semantic changes. The R6RS draft has piled feature on top of feature with no attempt to minimize. There are many minor points to the draft I dislike that I won't bother to mention - below I list only those issues which I consider the most egregious. * Identifier syntax. Anything done with identifier syntax can be done with normal syntax, replacing X and (SET! X Y) with (X) and (X Y) or similar. Thus this is purely syntactic sugar. It's an interesting idea, with the intent of making pseudo-variables, but at the same time complicates the semantics of the language. Identifiers may no longer be simple variable references, making code potentially more difficult to read. Moreover, it weakens every macro in the entire language by removing knowledge about the language the macros are expanding. For example, the simplest implementation of the LET-OPTIONALS* macro used in many SRFI implementations I'm aware of is the following: (define-syntax let-optionals* (syntax-rules () ((_ opt-ls () body ...) (let () body ...)) ((_ (expr ...) vars body ...) (let ((tmp (expr ...))) (let-optionals* tmp vars body ...))) ((_ tmp ((var default) . rest) body ...) (let ((var (if (pair? tmp) (car tmp) default)) (tmp2 (if (pair? tmp) (cdr tmp) '()))) (let-optionals* tmp2 rest body ...))) )) This takes advantage of the fact that only parenthetical expressions need to be bound to temporary variables. With identifier syntax, this is no longer true, and the above macro cannot even be written without helper macros or artificial pattern literals. This is a complication and inconvenience, but there are workarounds. There are other macros, however, such as the FAST-MATH macro at http://synthcode.com/scheme/fast-math.scm which are no longer even feasible. The introduction of identifier syntax makes it impossible to write this kind of macro. Identifier syntax is a cute gimmick but is seldom used, and no one is clamoring for it to write portable code. For the weaknesses it introduces, to make it a required feature of every Scheme implementation is absurd. * SYNTAX-CASE. Almost everyone wants low-level and unhygienic macros, but SYNTAX-CASE is an unfortunate choice of systems. Both syntactic closures and explicit renaming macros are older, and are simpler and more in the spirit of Scheme. SYNTAX-CASE provides a bizarre mix of low-level macros with high-level pattern matching, but a true low-level system should be orthogonal to such matching, allowing the programmer his choice of pattern matching or other utilities. * `_' and `...' patterns. It's unfortunate that R5RS macros can't match `...' as a literal in templates, but with the same restriction on `_' many existing macros will break, and moreover they have no easy workaround, requiring otherwise simple pattern matching macros to be rewritten in much longer and more convoluted low-level code. Simply allowing these as pattern literals solves the issue without introducing any new issues or ambiguities, and this was even suggested on the list but was ignored. * Versioning in modules. This is just premature. There are a lot of different possible ways of handle the problem of library versions, and they need more exploration before standardization. Everything done with versions in the current draft could be added in a backwards compatible manner in future drafts. * Unicode. Scheme has been around for a long time, and has seen many encodings come and go - there's no reason to bind it to a single encoding forever. An appendix or separate document(s) specifying behavior for Unicode-based implementations could always be written for compatibility. ** Normalization forms. STRING-NORMALIZE-NFD and the other three normalization procedures handle normalization at the wrong level. It's inherently an encoding issue, and is best treated as such. Providing this functionality at the string level forbids the implementation strategy of keeping all strings in the same normalization form - a very appealing strategy on many levels. ** O(1) string access. This suggests all Schemes to use UCS-4 character vectors for their string representation, discouraging the use of alternate representations such as UTF-8 and ropes or trees. ** Character-level case mappings. Case in Unicode is a string-level concept - providing case utilities at the character level encourages programmers to write broken algorithms. * I/O. The I/O system was totally rewritten for no reason, and all aspects of it controlled with gratuitous syntactic forms - second class forms which discourage high-level procedures. * Enumerations. There's simply no reason for this, since Scheme has traditionally used symbols for the same purpose. The one place where enumerations are truly required would be in an FFI, but the R6RS draft provides no FFI, and the enumerations provided would be insufficient for any FFI since they don't even let you override the integer values of individual symbols. * Exceptions. The exception system is far too large and over-specified. Exceptional situations should be treated as such, and implementations should be free to experiment with extensions in these areas. For these and other reasons I feel I have no choice but to vote against ratification of the current R6RS draft. The extent of the change is so great I feel the draft can only be considered a new Lisp dialect - the name `Scheme' does not suit it.
IMPORT LEVELS: The draft does not specify how to write portable libraries that define or use macros with literals. In particular, the draft does not say whether uses of literals such as DEFINE, ELSE, ellipses, and so on (in other words, the arguments of free-identifier=? - when the comparison succeeds) count as references for level checking. Thus, users will be forced to resort to cargo-cult programming in the hope that their code will be portable. RECORDS: I think the constructor-related parts of the syntactic record layer and of the procedural layer are bewilderingly complex. The custom constructor design is a good example of premature generalization and piling feature upon feature, and since their current API adversely affects other aspects, such as modularity, of the design, as discussed on the list by Will Clinger and myself, I believe it would be better to drop custom constructors completely unless a simpler and better design can be agreed on. Such a design may be better left for a future SRFI. Only a minority of record applications use custom constructors, and these can always be expressed in terms of standard constructors (we have libraries for hiding unexposed names from the client if necessary). By the way, I do not think inheritance makes custom constructors necessary in the base API, since users can easily roll the current custom constructor functionality themselves without, I believe, loss of performance or modularity. LIBRARY VERSIONING: I do not think that versioning information should be in source code. Also, the version reference syntax is very complex and rather ugly. ENUMERATIONS: I cannot reconcile the presence of this library with the philosophy of prior Scheme reports or with the r6rs mandate. It seems an example of premature generalization and piling feature upon feature. I would prefer that it be dropped completely and left for a future SRFI if enough people feel the need for it. SET!: There is no way of importing set! for a single level. This limits the languages that a library designer can create. I would suggest the addition of a library (rnrs mutation) that exports only set! for level 0. The (rnrs base) library can still export set! for levels 0 and 1 if desired. LIBRARY INSTANTIATION: The draft links library instantiation and visitation not to import clauses, but instead to the presence of identifier references in the client, and provides no guarantee of instantiation otherwise. Again, I worry that this may force users to resort to cargo-cult-like programming (such as inserting otherwise unnecessary variable or macro references in client code whose only purpose is to force an instantiation or visitation) in an attempt to ensure portability. I would urge instantiation and visitation to be guaranteed at least for the declared import phases (this should be compatible with both explicit and implicit phasing models). CONDITIONS: Although the conditions API has seen improvement, I worry that the division into simple and compound conditions, along with the infrastructure required to manipulate these, is overly complex and may be awkward to use in practice. I would love to see a simpler design - perhaps something as simple as an alist-like object may work quite well and allow the current plethora of types to be replaced by properties instead. ======= I do not consider the following objections dealbreakers, but I would like to list them for the record: SYNTAX-CASE: The description of the mark-antimark algorithm significantly lengthens and increases the complexity of this chapter. It is hard for me to understand despite being an implementor (granted, I use a different algorithm). The draft could be simplified by cutting this operational description, especially since this is not the only algorithm, or even (to me) the simplest algorithm for implementing hygiene. A more declarative description in the spirit of r5rs, as already given in the introductory paragraphs of the draft section on hygiene (perhaps with some small refinements and examples), already says it all and could make this chapter considerably cleaner and shorter. COMPOSITE LIBRARY: I do not think (rnrs) should export define-syntax and let[rec]-syntax for level 1, or syntax-rules for level 0. In the context of the (rnrs) import, there is nothing one can do with these bindings at those levels.
Deliberating on the latest R5.97RS draft I find much that is agreeable about it, and it would be tempting to vote for its ratification. Indeed if but the programming language described therein would be named anything else than Scheme, it might seem the promising start of a practical and useful modern Lisp dialect. Yet as the R5.97RS main and library reports still read today, the resulting language is most definitely not Scheme. My primary issue with the draft is that it betrays the spirit of its very own opening paragraph: 'Programming languages should be designed not by piling feature on top of feature, but by removing the weaknesses and restrictions that make additional features appear necessary.' I should very much hope that paragraph will never be removed in future RnRS reports! Evaluating the rest of the main and library report against that principle, I think it stands out that the draft has simply suffered considerable feature creep and is vastly overspecified and overcomplex. In a word, it is too ambitious (or presumptuous, depending on your point of view). I'm convinced the draft as it stands would derail Scheme, in the sense of putting the language on a course that it is unlikely could be easily corrected through later RnRS iterations. Thus I must at this time, with apologies to the editors, vote against ratification and hope that there will be enough dissenting voices to reopen the editorial process. If the vote concerned only the main report in something not too far from its present form, ratification would not be an unfeasible prospect; and this despite the report having almost doubled in size. I do share others' misgivings on issues such as requiring the full numeric tower and chaining Scheme at the hip to Unicode; still, the main report all in all appears decent, and a standardized library definition facility, even if the current proposal seems rather overcomplex, would be a most important practical benefit provided by core R6RS. However, the proposed standard library report is simply unacceptable. Not only does it gratuitously eschew important and widely-used existing SRFIs (such as the SRFI-1 list library, and SRFI-69 hash tables) in favor of its equivalent incompatible functionality, but one must ask why features such as, say, byte vectors, enumerations and hash tables should even be included in the RnRS reports in the first place? The desire for a standard library is widespread, both for reasons of portability and practicability, but I think it is clear that when it comes to library functionality, the SRFI process has proven itself and works better than the committee process being voted on here. Attempting to evolve a standard library through the rightly slow- moving RnRS process seems to me shortsighted and counterproductive in the long run. Thus, I consider the standard library report largely superfluous and indeed harmful. Instead of attempting to set in stone a controversially large standard library with the RnRS process, I believe the R6RS committee should strictly confine itself to the core language only, and fully embrace the SRFI process for the standardization and dissemination of all non-essential library features.
There are many flawed aspects of R5.97RS, which time does not permit me to cover. I will describe three. Macros In the R5.97RS introduction: Scheme demonstrates that a very small number of rules for forming expressions, with no restrictions on how they are composed, suffice to form a practical and efficient programming language that is flexible enough to support most of the major programming paradigms in use today. This was true of R3RS and R4RS, but not for R5RS and R5.97RS. In R3RS and R4RS there were a small number of rules for forming expressions: DEFINE, QUOTE, LAMBDA, IF, SET!, BEGIN, COND, AND, OR, CASE, LET, LET*, LETREC, DO, DELAY, QUASIQUOTE, and combinations. I have 70,000 lines of mathematical, scientific, engineering, database, and scripting software written in (R4RS) Scheme showing that this small number of rules is "flexible enough to support most of the major programming paradigms in use today." One reason that this large multi-author corpus of (free software) Scheme code can be actively developed and maintained is because R4RS code is very readable. In a R4RS compliant file, it is easy to see which lists are expressions which might be evaluated; there are no new syntactic tokens which can be mistaken for identifiers. The use of LAMBDA in arguments to procedures establishes binding scope, no matter what those procedures do. The significance of this achievement by R4RS is not widely appreciated. Procedure are sufficient to create nearly any new features. Even new control features do not require new syntax. EVAL, VALUES, CALL-WITH-VALUES, and DYNAMIC-WIND, added in R5RS, are all procedures. In the R5RS introduction: More recently, Scheme became the first programming language to support hygienic macros, which permit the syntax of a block-structured language to be extended in a consistent and reliable manner. Extending the syntax would be desirable if Scheme's "small number of rules" were *not* sufficient "to form a practical and efficient programming language ...". But SLIB and other softwares show that R4RS is sufficient. The effect of adding macros to Scheme has been the proliferation of mutually incomprehensible language dialects. We have seen the growth of "convenience" macros like WHENNOT and UNLESS, use of macros as a substitute for compiler optimization, and use of macros to avoid using symbols as tokens. None of these uses increases the expressive power of the language. In a reusable software world, the use of incompatible dialects is detrimental; it is only through documenting, publishing, and deliberating, say in a SRFI, that new forms should be adopted into that "very small number of rules for forming expressions". Arrays Computations have been organized into multidimensional arrays for over 200 years. Applications for multi-dimensional arrays are widespread and continue to arise. Computer graphics and imaging, whether vector or raster based, use arrays. A general-purpose computer language without multidimensional arrays is an oxymoron. Although multidimensional arrays are the subject of SRFI-25, SRFI-47, SRFI-58, and SRFI-63, and portably supported by SLIB, search of http://www.r6rs.org/r6rs-editors/ finds nothing to indicate that the editors ever considered their inclusion in R6RS. Can R5.97R Scheme be extended to support SRFI-63 arrays? Libraries SRFI-63 redefines EQUAL? to work on arrays. But in the R5.97RS module system, a SRFI-63 library exporting EQUAL? will conflict with the RNRS language export of the same name. Thus any import of the array library (and there are many in SLIB) will require that EQUAL? be excluded from the import of RNRS. Thus the R5.97RS library mechanism fails to be modular; users must know and exclude from modules any exported redefinitions, whether or not they use those identifiers! This is more than an inconvenience. R5.97RS prevents the sort of language extensions which are a hallmark of LISPs. Consider SLIB's COMMUTATIVE-RING module, which captures and redefines *, +, -, /, and ZERO? to work on expressions: (require 'commutative-ring) (set! *ruleset* (combined-rulesets distribute* distribute/)) (define a 'a) ... (define z 'z) (* (+ a b) (- a b)) ==> (- (^ a 2) (^ b 2)) (require 'determinant) (determinant '#2A((a b c) (d e f) (g h i))) ==> (- (+ (* a e i) (* b f g) (* c d h)) (* a f h) (* b d i) (* c e g)) In R5.97RS, the DETERMINANT module bindings for *, +, -, and / would be unaffected by the COMMUTATIVE-RING extension. Even creating a new language binding to supplant RNRS is no help without modifying the source code of the DETERMINANT module. The R5.97RS library system has significantly reduced the expressive power of Scheme; it is no longer possible to extend built-in procedures to new types in a modular fashion. Conclusion The framework to extend R4RS and R5RS (through redefinition) made it possible to provide those features that Scheme lacked in a portable and modular fashion. R5.97RS not only lacks the multidimensional arrays essential to my work, it has removed the means for remediation of its deficiencies.
- Requiring the full numeric tower works against using Scheme in smaller environments such as embedded systems. - Procedures such as div0-and-mod0, exact-integer-sqrt simply do not belong in a base language. In fact a lot of the numerical procedures belong in a library. It is perfectly meaningful to say that if a specific library is implemented, it must meet the entire spec. but *all* libraries must be optional in a base language and a base language implemener *does not* have to provide all libraries. Even C does this! Surely, one of the rationale for Scheme was minimalism? - R6RS is not good enough for commericial usage since it lacks a FFI to interface it with libraries implented in C/C++ (such as system libraries, graphics etc). And it specifies too much for an experimental language. Neither fish nor fowl. - I would have preferred R6RS to be *smaller* than R5RS, where some of the required features get moved to optional.
When this process started, I expected to reluctantly vote for approval. However the discussion has been very illuminating, and the arguments against ratification have been both cogent and convincing, while those in favour have, at least to my mind, been less so. Here are the arguments that convinced me. Some are due to an excellent post by Alex Shinn dated 29-May-2007, while others are distilled from posts by David Rush and Jeffrey Mark Siskind. First, there is the question of why we want or need an Official Scheme Standard, and what the goal of the "RnRS process" should be. It seems to me that, broadly speaking, the draft R6RS has the goal of making Scheme be like C or perl: a workable programming language like other programming languages. This seems reasonable on its face, but Scheme has survived for a long time by not being a programming language like others, but rather by being an oddball: minimally specified, usable for real-world programming only by using numerous implementation-specific features, but ideal for teaching and research. Scheme is the defacto lingua-franca for programming language theory. R6RS and its associated mindset flies directly in the face of Scheme's historic strengths, and to my mind risks diluting them. If this were to occur it would be a disaster. In other words, it is not clear to me that the draft R6RS is moving Scheme in an appropriate direction. Second, it is not clear to me that the draft R6RS even specifies the right things to make Scheme industrial strength. This argument was made quite forcefully by people who actually do use Scheme in real-world settings. Third, the draft R6RS contains many features that are highly complex to specify and that are quite un-lispy. The enum stuff comes to mind. Records. The exception handling system. Symbol macros. Unicode enshrined. Each is individually motivated, but all together we end up with a very large ball of mud. The size of this ball directly impairs one of Scheme's important features from an industrial perspective: its role as a small language suitable for automatic program transformation and other PLT sorts of techniques. To sum up: I have come to the conclusion that ratification of the draft R6RS will not be healthy for the Scheme community. This draft, and the process behind it, puts the mindset of the community at risk, and is moreover unlikely to achieve its intended effect of industrial acceptance. For these reasons, I have been reluctantly dragged into a negative vote.
The following is not as polished as I'd like it to be, sorry. Most of my codes have the following features: 1. Homogeneous numeric vectors. 2. Various I/O features (read/write pgm/ppm/... files, open tcp sockets, .. 3. Unsafe arithmetic/list operations/... The standard does not explicitly help me in these areas. I'll comment a bit more. Re: Unsafe arithmetic and other operations. I understand that draft does not address these issues; that is fine. Re: Homogenous numeric vectors. The suggestion is made in the rationale that bytevectors plus sealed and opaque types can lead to efficient implementations of homogeneous vector types. To my mind, this assumes the existence of a "suitably smart compiler", and I no longer believe in such a thing. I appreciate Will Clinger's attempts to explain how various features in the proposed draft (including this one) could be implemented efficiently, but I don't think that these efficient implementation of specific features will be found in most R6RS systems. I've participated (mainly as an observer) in compiler development (gcc and gambit), and there are a lot of considerations that people bring to the table; a fancy implementation of a specific feature that is nearly trivial to implement as a primitive (homogeneous numeric vectors) is going to be hard to get to the top of a Scheme implementer's priorities. The parts of the proposal that I most object to are bytevectors and the I/O library. As the draft explains, these two features are intertwined. I think both of them are ad hoc, having a plethora of related procedures that still do not cover the facilities offered by other R5RS I/O extensions in existing Scheme systems. The fact that bytevectors are, by their nature, type aliasing nightmares is too lightly ignored in the draft. Making these the basic implementation strategy of homogenous vectors makes it harder for Scheme systems that compile to C for portability to implement homogeneous vectors efficiently, due to the C aliasing rules. (The authors of the draft clearly had certain implementation strategies in mind when they inserted or deleted various features into the draft; in this case I think their estimate of the affect of this feature was incorrect.) And this situation does not lead to portable code. (And, BTW, IEEE-754 does *not* specify the bit patterns for single- and double-precision floating-point numbers in a way that this report seems to think can be exploited in bytevectors.) I tried to go over some of my own codes to see if the changes in the I/O system would allow me to do what I wanted to do inside R6RS, either (what I would consider) reasonably, or at all. The answer generally was no. I consider the proposed I/O system and bytevectors to be a solution to problems that are nowhere near as important to me as they appear to the editors of the draft; at the same time the draft doesn't offer solutions to the problems I find in my code. I'm stating this in a very personal way so as not to claim universality for my perspectives or needs, but I think my concerns are valid. I consider the proposed bytevectors and I/O large parts of the draft that would be difficult or impossible to fix in R7RS, so I vote no.
Although my initial impression of the draft was mildly positive, after looking it over more thoroughly I am voting against ratification. My vote is based on my overall impression of the draft, but here are some illustrative examples of particular things I don't like about it: Fist, the problem of two record systems that don't quite work together. This was raised by Will Clinger, most recently in his essay "Fixing the Syntactic Record Layer" <http://www.ccs.neu.edu/home/will/R6RS/essay.txt>. Second, the fact that you cannot simply take a record value and access one of its fields by name. I explained my problem with that on the mailing list <http://lists.r6rs.org/pipermail/r6rs-discuss/2007-August/thread.html#3145> <http://lists.r6rs.org/pipermail/r6rs-discuss/2007-August/thread.html#3146>. None of the explanations given for this in the rationale, the mailing list, or the srfi discussions satisfy me. (And the only direct reply seemed to misunderstand the example -- we want a container that requires certain behavior of the values it contains while not requiring that they be on an approved list or inherit from the same ancestor. Importing the accessors of each type of value we wish to contain makes the container's import list the approved list.) Third, the condition system with its simple conditions and compound conditions. After reading through this part of the specification and disliking it, I found a reasonable counterproposal on the mailing list <http://lists.r6rs.org/pipermail/r6rs-discuss/2007-February/thread.html#1458>. It was rejected with a statement that it conflicted with other decisions of the editors and did not appear to be different in any other way. (It is, however quite different. It makes all condition types record types, eliminating the need for almost everything in section 7.2, and it makes it much easier to handle an exception by supplementing the condition with more information and re-raising it.) Those three are just illustrative examples. I am casting my vote based on my overall impression of r5.97rs: Too many things in the draft are designed primarily to work around limitations imposed by other things in the draft. The explanation of the condition system in particular helped me crystallize what I had felt while reading the draft. It was yet another explanation of the form "We must do X because we have decided to do Y and Z." Meanwhile, Y and Z are required by W, which is required by P and Q, which we need because we have X and Y. The editors are happy to explain each feature by pointing to the features that require it (or at least conflict with every alternative they are aware of) but don't seem to have considered the glaring possibility that all are bad and that this is why they are mutually forcing each other into a series of workarounds. The introduction to the draft still begins with, "Programming languages should be designed not by piling feature on top of feature, but by removing the weaknesses and restrictions that make additional features appear necessary." I feel I understand that principle much better now that I have seen r5.97rs itself violate it. If you start by planning to add lots of features, add them in ways that introduce weaknesses and restrictions, then refuse to remove or replace any of your additions as a way of repairing the damage, you end up with a mess that piles workaround on top of workaround and calls them features.
There are several reasons why I am unable to vote in favor of this set of documents. First, I am deeply disturbed by the size and scope of the proposed changes to R5RS. While many of these changes are sensible, there are very many changes, and rather than getting to vote on each change separately, we're forced into voting on all of them at once. This is very like the way national deliberative bodies work, and is even more distasteful in this context. A more incremental process would foster more thoughtful development, allow users and implementers to digest and understand the strengths and weaknesses of each feature before moving on to the next. (I certainly don't have time to fully understand all that is being proposed here.) One interpretation of this process is that it's driven by fear: the fear that the current set of authors have only a limited extent of control over the standards process, and are trying to make the most of it while they can. I don't think that's exactly what's happening here, but I do think there's a certain amount of distrust in the future, based more than likely on the dismal experiences of the past. Nonetheless I think we should start from the assumption that small successes now will lead to more small successes in the future, and that over time those successes will accumulate to make something great. We have to trust our ability to work together, and we have to trust that spreading control of the standards process more broadly through the community is best in the long run. So, what I'm advocating here is something more like the "bazaar" software development model: release early, release often, and be open to participation by the community. The second problem I have is the fairly low priority given to backwards compatibility. This is made all the more important by scope of the documents. I understand that the standard answer to this is that implementations are expected to provide mechanisms for switching between modes -- but this doesn't really address what to do with existing bodies of code. It also makes it more difficult to update existing code to the new language, since there's no incremental update path; each program must be completely transformed all at once, which effectively means it will never happen. Contrast this with ANSI C, for example, in which it's possible to incrementally update programs from traditional to ANSI C, and have them continue to run when only partially updated. This is a huge win that I've taken advantage of in my own code. The third problem I see is that two core features of the language have been designed as entirely new sub-languages: specifically, the module system and SYNTAX-CASE. Not only are these new languages, but they are declarative languages, which makes them fundamentally different from the core language, which has always been imperative. Worse, these sub-languages solve problems that could have been solved by application of the core language, meaning they lead to additional cognitive complexity while getting little in return. The module system is basically a way to tell the linker how to construct programs from parts. Rather than invent a new language to do this, it's possible to build the linker such that the programmer can insert code to control aspects of the linking process. Such code could do _more_ than the current module system does, and because of the added expressivity, it could do so more concisely in many cases. For example, I sometimes use a trivial module system in which names starting with "%" are local, and all other names are exported. This is a trivial program to write, and doesn't depend on the details of the names, but it can't be said at all with the proposed module system. SYNTAX-CASE has similar problems, although not as extreme: it implements a term-rewriting system, with limited programmability, to solve a problem for which there are significantly simpler solutions. This sub-language introduces a new kind of variable that behaves differently from the variables we're used to, and pushes pattern-matching and templating to the center of the macro-writing process. Yet with this added complexity it is arguably no better than the syntactic closures or explicit renaming mechanisms proposed years ago, which have very little cognitive overhead.
I think it is pointless to ratify a Scheme standard that doesn't hold true to the founding principles -- expressiveness and simplicity -- of Scheme. The key benefit to me, portability derives from standardization; but developers of significant compilers do not support this draft -- this fractures the community and reduces the likelihood of portability. Another summarized it this way: this draft seems to nail down the (more-or- less) easy-to- nail down things, and reduces the scope of solutions to the difficult issues without making substantial progress on them.
Programming languages should be designed not by piling feature on top of feature, but by removing the weaknesses and restrictions that make additional features appear necessary. The R6RS draft strays far away from the simplicity that characterized earlier versions of the report. As a result, the effort required to implement a standard-compliant Scheme becomes much larger than before. This will discouraging future implementors, endangering the diversity that is one of Scheme's present strengths (there are Schemes running in almost any imaginable environment -- embedded, desktop, in a browser, on top of Java and Ocaml etc). Furthermore, because of this complexity (as well as because R6RS is controversial) many existing implementations will choose not to support R6RS, thus splitting the Scheme community and codebase (some authors will choose to write R6RS code that will not be directly usable by those running R5RS-only implementations). I believe that, given Scheme's present maturity, the proper way to evolve and enhance the language is via SRFIs, which provide a more democratic and less biased process, and which minimize the destructive effect of poor design decisions. Other reasons for which I do not believe the R6RS should be ratified are: identifier macros, which make the job of code-walking macros much more difficult (especially as there is no way to programatically expand macros); the syntax-case macro system (even if relegated to the standard library); the complex and over-specified exception system; and immutable pairs, which may make optimization easier, but do not fit at all with the practice and spirit of Lisp.
It seems to me that, at 91 pages, the proposed Revised^6 Report would make Scheme something bigger than it should be. I think that this violates an important part of the spirit of Scheme, which is to keep the language small, so that learning and implementing it remains relatively easy. Yet the proposed Report, as far as I can tell, fails to address some criticisms that are more than likely in our day and age, such as the absence of network connection capabilities. If such features are to be omitted from the Report, why could not many other features be deemed "recommended yet optional", and grouped in a common library, that does not have to be a de jure standard? Other languages appear to live quite successfully with de facto standard libraries that are separate from the language description. One thing I definitely would not like is to have the R6RS be a widely-ignored standard, in the way that, many years after its publication, C99 has but very few implementations, none of them popular.
The shortest explanation for my dissatisfaction with the R6RS is that it appears to have gone fairly far off-track. There are some things I like in it, and would like to vote 'maybe' except for the core structural issues that I see. I have always felt that the brevity of the RnRS spec was one of it's stringest points. Now, with R5.97, the document has expanded to cover 4 interrelated specifications - which would not be bad in and of itself, but the documents seem heavily interdependent. Make no mistake about it, I actually *wanted* the standard split into core and library components, but I was looking at something rather closer to the SML 2000 split. The library machinery; however, is quite nice and I would like to see it preserved. In fact, it is the primary reason why I would like to vote maybe or even yes. It specifies modularization in terms of build processes, which is exactly the right level of abstraction. One minor error though seems to be the in the definition of top-level programs: it appears that only one import form is allowed for a program, which will certainly be violated in an interactive session. Perhaps I have missed the text which allows the REPL to behave differently from a program - but I'm not sure that such a behavior is actually desirable, anyway. An example of where the library/core breakdown is inadequately addressed is the persistence of DYNAMIC-WIND. It has been clearly shown that DYNAMIC-WIND (and R5RS CALL/CC) is implementable in terms of R4RS CALL/CC, but that the reverse is not true. Given the renaming facilities available in the library system, it would seem *really* obvious that R4RS CALL/CC should be in the core and R5RS' DYNAMIC-WIND and CALL/CC should be a separate library. I am quite ambivalent on the topic of exceptions and conditions. I have found that the under-specification of R5RS in this area has actually led me to write better and more comprehensive error handling code. However; I have often wished for a better standardization of error-handling procedures across implementations. The gripping hand holds that the exception and condition-handling behavior is insufficiently worked out. First of all, this functionality *should* be part of the core specification - as is shown by the inclusion of a section on exceptions in the formal semantics. Secondly, the interaction of exceptions and continuations is not clear. It is clear that someone has a notion of how it should all interact, but that does not come out in the document. This last issue is a definite showstopper and points out something that I would very much like to see in the Scheme specification: a solid model for asynchronous events. That alone would be justification enough for R6RS, but it is sadly lacking. A sound asynchronous semantics would enable more things than I can even begin to list at this point. I also feel that the approach to Unicode and non-ascii character sets to also be immature. There are two areas of concern here: program text and I/O. In Scheme the line between these two blurs because of the traditional representations of programs as s-expressions. After seeinng the example of Ruby, I am not convinced (in fact I have begun to be unconvinced as Ruby had its origins in a non-english environment) of the value of supporting unicode for program text. That said, the capability of sexp read makes it hard to avoid. I will only say that the addition of Unicode escapes is ugly to say the least. I am actually moderately pleased with what I see in the I/O system changes. I feel there is a fairly sound basis for extensions to include non-blocking I/O and (dare I say it) interrupt-driven I/O. Multiple-return values *still* has not been fixed. The most straightforward solution is simply to make all continuations multi-valued - or rather that apply a single-argument continuation to multiple values results in the coercion of the actual arguments to some list form. I hate to appeal to Ruby for examples of The Right Thing, but this is a Ruby practice which does seem to work well in practice *and* it would alleviate a major asymmetry in Scheme continuation semantics. It would actually be even better to eliminate multi-valued continuations entirely, but that would be at the cost of breaking existing code (SRFI code even). Personally I have shunned call-with-values and use explicit CPS whenever I have multiple values to return. There are a number of other issues about which I have heard rumblings from the more editorially involved and/or experienced implementors which leave me very worried. While I have not been able to fully evaluate their claims, I will state that I am in agreement with any concerns which reduce the ability of compilers to optimize my code. I am also quite concerned that there are gotchas waiting for prospective implementors (I *do* intend to become one :) - the R5RS spec was much clearer in that respect. A petty irritant for me is the official sanction of square brackets. Given the extensive training the my optical neural networks have received, I find the use of square brackets ugly and unhelpful in reading code. They create a very discordant visual rhythm and should be summarily outlawed. Square brackets are a gross violation of the LISP Party Ethic and offending implementors shall be required to submit thorough self-criticism of their motivations and then will be summarily shot. I really mean this. Finally I will say that it is nice to have a 3-state vote, although perhaps a continuous rating system would have been even better yet. I am not happy enough with the R^(5.97)RS to vote 'yes', or even 'maybe', but I am not far from it. I suppose the fault is mine for not engaging the process at an earlier date. Either way, my vote for the current draft is: NO.
R6RS completely breaks with Scheme's traditional values of simplicity, and throws in gratuitous assortments of needless features, while lacking coherency and generally appearing to be thrown together in haste. R6RS is controversial even among the R6RS editors, and tries to standardize insuffienct compromise solutions for things that are better left unspecified. R6RS is a misguided attempt to make Scheme more suitable for the mainstream, but effectively does the very opposite by removing the assets that always distinguished Scheme from other dialects: smallness and simplicity. I feel not represented by the people that call themselves 'R6RS editors'. This s-expr text format is idiotic. What the heck do you mean with 'an explanation is mandatory'? Need a refresher in democracy, folks?
I think an update to R5RS is needed, particularly to add a module system. Unfortunately, the current proposal doesn't simply add what is missing to R5RS: it tries to do much more. However we put it, the base library is a fundamental part of the proposal. But its design ignores a significant part of the SRFI process, for example by being incompatible with SRFI-1. It is also big and gratuitously complicated. The records, I/O and exceptions are good examples of the unneeded complexity. I'm against making Scheme a bloated and complicated language. I think the current proposal doesn't respect the philosophy of Scheme.
For me the single most important aspect of R6RS is what I will refer to as specifying a suitable system for "standardized portability": portable programming for library and application developers who want to move more easily beyond Scheme's solid established niches, while not endangering the virtues of the language that support both these niches and what we are trying to accomplish beyond them. The core language is the crown jewel of Scheme, and most of us would say the crown jewel of programming languages. In its current minimalist form, it is critical to Ivan Raikov's "holy grail of high-performance scientific computing", and the work of many others. But the failure of our community "to build a large collection of shared libraries" (Ryan Rhodes Newton) must be addressed. Or as Arthur A. Gleckler put it: I want to help make sure that R6RS maintains the right balance between the diamond-like jewel Scheme has always been and the practical everyday programming language that we have always wanted Scheme to be. The proposal took the tried and true approach of making a core language definition, a library mechanism, and a set of standard required libraries, and I approve of this. It is the only approach I can see that satisfies the needs of all the stakeholders. If done right, this approach does not have to compromise Scheme's current strengths---in fact, this can profitably be used to reduce the size of the core, while at the same time a few necessary things are added to it, like exceptions. While I appreciate the concerns of those who want to keep Scheme minimalist, to the point that I am voting against ratification first and foremost because this proposal does not satisfy them, I fail to see how any considerations beyond hooks in the core for library efficiency provide a compelling reason to not standardize it beyond the core, for those who want to get work done beyond the domains a minimalist core excels in. The devil is in details, and that is where this proposal most grievously fails, in the particulars of drawing the lines between the core and its various libraries at various levels. I therefore I pose this question: if the proposal is sufficiently bad that it endangers what we've got in an effort to get something more, why accept it? It is rather common in this sort of effort to lose what one has and thus never gain what is attempted. It is better to reach *correctly* for something new, or as David Rush in comp.lang.scheme put it "In RnRS, the middle 'R' means 'Report' and initially reflected the common and agreed practices in the Scheme community - this is a *retrospective* term and could never reflect the bleeding edge of language innovation." There is much good in this proposal; a lack of time and relevance to the voting process prompts me to focus on only two specific issues related to the all-important library mechanism that I caught on my first reading of it, and that I found had prompted formal comments: 1. The reason for ABSOLUTELY prohibiting linking to multiple versions of the same library per formal comment #130 is very weak. Scheme and the LISP family in general are incisive, powerful languages that give their users great power that can be easily misused. They are not "restraint" languages (e.g. Java), and the "potential for confusion" here seems to be balanced by the information and control the library system gives the user. I am certain that situations as outlined in the comment will occur and harm the efforts of developers, if a sufficiently rich set of library implementations following the standard's mechanism are developed---which is the motivation of creating such a library mechanism in the first place. Those of us who have plenty of scars from "DLLHell" are POWERFULLY motivated to avoid anything like it, but this goes too far, too against the grain. This single problem's damage to the raison d'etre of libraries and R6RS itself is a show stopper. 2. I feel that Scheme should accommodate the desires of library writers to intermix definitions and expressions [insert usual platitudes about needless restrictions---and how Scheme is perhaps more than anything else a system for communicating to other programmers...]. I found the response to formal comment #212 to be singularly unimpressive: that this "might be more useful, but there is no a priori reason to think so" is in frank contrast to the code survey made to reply to formal comment #117. The crowning touch of the response's justification by how it might confuse a Java programmer learning Scheme was for me the final nail in the coffin of R5.97RS. What I'd like to see happen if the proposal is not ratified and the community tries again for a R6RS: It should be *in the direction* of previous revised reports in requiring unanimous consent *for the core* (which includes the library mechanism, but precious few libraries). Therefore the process in the future must continue to require super-majorities for core ratification and maybe even greater ones than the current 60%---and that helps to properly draw the line between it and the required standard libraries. Library ratification does not need to be as strict: as long as they are "acceptable" and have nothing dreadfully wrong with them, it is better to have usable standards than no standards at all, and in theory the SFRI process has allowed the community to discover what works in practice and it worth standardizing. Therefore if this proposed version of R6RS is not ratified (and even if it is), I recommend serious consideration of separating the standardization of the core and standard libraries. They're different beasts for sometimes different audiences. As for what that next R6RS should be: it should define as absolutely minimal a core as is reasonable, keeping all the good things in R5.nnRS, especially exceptions (I think) and a requirement to implement the full numeric tower. Raising the bar for a minimally compliant implementation is worth it for these features---but maybe not Unicode per se, so that the embedded community is not overly taxed by that requirement. The above core will include a library mechanism like the proposed one with the show stopper problems fixed. Then a standard library set *with a reference implementation written in pure Scheme using only the core language* (and other required standard libraries). Part of the required standard core will be hooks required by the above standard libraries needed for minimal efficiency. Implementors wishing compliance with the full standard need only implement the core and ship the reference libraries with it. They and their users can write more efficient implementations of the standard libraries that take advantage of their lower level extensions and special capabilities as they see fit. The core should be satisfactory to the "minimalists" as long as it is not soiled by the additions and is not too "big" for them. The total should be a satisfactory base for those who want do things that would move well beyond what the core supplies. (The above is mostly from a discussion in comp.lang.scheme.) In the longer term, certain things should be added to the core, e.g. I think that continuations should be extended to full first class status, but it should become pretty stable pretty soon. *Ideally* there should be no major *changes* (e.g. case significance) to the core after not many more RnRSs. What I'll do if the proposal is ratified: I will decide that we no longer live in an civilized age ( http://xkcd.com/297/ ), for official "Scheme" will have lost too much of the elegance and correctness that has up to now defined it (I didn't realize it at the time, but so did our parent community when they standardized on Common Lisp, a harsh object lesson in language stagnafication we would do well to remember). There are many signs that ratification of this proposed standard will shatter the Scheme community. For many language implementors, the position of the standard is akin to that of Glendower in Shakespeare's King Henry the IV: I can call spirits from the vasty deep. Because as Hotspur replied: Why, so can I, or so can any man; But will they come when you do call for them? This standard if ratified cannot perforce move the entire community to it. Enough of the wrong things in the proposal can never be undone, and it is very unlikely the splintering of the community that this proposal will cause if ratified will ever be undone, precisely because these wrong things cannot be undone. The lead developer of my favorite Scheme implementation will not vote in favor of this proposed standard, and I would not be at all surprised if he and others fork off their own standard ... call it "Uncommon Scheme". And I think there will be more than enough people going in this direction to make a community with critical mass, That would be an truly unfortunate development, but while my most important personal interests are best served by a widespread acceptance of standardized portability, I cannot support it if it destroys that which makes Scheme so attractive in the first place, including the core upon which my other interests depend. - Harold
I find that Scheme R5RS has become a convenient tool for research and education because it is small and elegant. Its orthogonal feature set invites experimentation with the language. Because of its small size, the programmer has to learn only a few fundamental principles in order to master it. Consequently, there is a proliferation of competing R5RS implementations, which puts Scheme in a unique position, as no other current programming language can claim it has fostered such a diverse software ecosystem. I believe that the R6RS proposal is moving Scheme in a fundamentally wrong direction. It is my opinion that the Scheme community will benefit far more by rejecting the R6RS proposal and continuing the experimentation and innovation fostered by R5RS, than it would benefit from any potential interoperability gained by a new and far-reaching standard. I believe that a high-level language based on lambda calculus must permit precise formal algorithmic specifications of software systems that are invariant on all possible hardware platforms, operating systems, and that are independent of data formats, protocols and standards. Historically, Scheme has fulfilled such a role, and it is my opinion that any features that specify implementation details, as opposed to formal semantics and abstract implementation requirements, do not belong in the core language. The SRFI process has evolved to be the universally accepted standardization process for Scheme libraries, and R6RS must not attempt to subvert it. Each library must undergo its own standardization process. If one wants a standardized Unicode Library for Scheme, then the proper way is to develop an SRFI for a Scheme Unicode library and convince the implementors and users of existing Scheme systems to adopt that SRFI. However, the R6RS proposal demands a large set of extra libraries that are not universally adopted by existing implementations. It does not include widely used and implemented SRFIs, such as SRFI-1, yet it features SRFIs that impose very particular restrictions in fixnum representations, it relies heavily on Unicode, which may evolve and change as a standard, it imposes an imperative hashtable API, where many Scheme implementations feature purely functional dictionary structures, If the core language is sufficiently minimal and well-thought-out, and if the libraries are sufficiently high-level and general, the issues of organization and interoperability can be left to the implementations. A good language standard should support interoperability, not impose it. Following is a list of R6RS proposal features that I consider unnecessary and complicating the language: 1) Unicode It is perhaps better to remove those features of R5RS that prohibit Unicode implementation (such as char->integer and integer->char), and relying on extended SRFI-13 and SRFI-14 for Unicode support. If Unicode support is relegated to a library, the character and string representations will not be rigidly coupled to the language specification, and core Scheme will remain implementable on platforms without Unicode support. 2) Byte-vectors The core language must only include abstract vector type. Having particular types of vector representations is precisely the domain of SRFIs. The R6RS proposal byte vector syntax is not widely agreed upon, and it requires two sets of vector procedures in the core language. 3) Lists SRFI-1 is a well-thought API, which is widely implemented and used in the Scheme community. Yet the R6RS proposal uses incompatible names to several SRFI-1 procedures. Although R6RS claims to emphasize the role of the community, it seems that it is ignoring a previous community effort, and puts future SRFI work in a questionable position. 4) Dictionaries & hash tables The core specification must not mandate any particular standard for dictionary structures, as the existing implementations vary widely in APIs. A side effect free association list structure may be permitted, but anything more sophisticated must be relegated to a library. 5) Exceptions The R5RS report used the phrase "an error is signaled" to indicate that implementations must detect and report an error, without going into specifics. In contrast, the R6RS proposal requires the signaling of exceptions, and it goes further to propose a complex and very specific hierarchy of exceptions. Once again, common practices in the Scheme community are ignore, and instead of relying on the SRFI process, exceptions are mandated in the core language. 6) Modules The enforced phase separation in the module system described in the R6RS proposal overspecifies the module system and disallows different implementation strategies, thus prohibiting the Scheme community from experimenting and innovating. In addition, the module system becomes an obstacle to the use of Scheme as a teaching language, because beginners now must deal with it long before it can be explained to them why. Syntactically, library descriptions need to be enclosed in an additional layer of parentheses, as opposed to a single definition at the top of the file. The versioning system is complex and not obviously necessary, or tried in practice. Again, matters like these must be relegated to the SRFI process. 7) I/O All but fundamental I/O primitives should be put in a library. As with vectors, non-abstract operations do not belong in the core language. 8) R5RS compatibility The identifier macros in the R6RS proposal break R5RS compatibility by eliminating a specific invariant on which R5RS programs and macros can rely, namely that a reference to an identifier has no side effects. With identifier macros as proposed for the R6RS, an identifier may not actually be a variable reference, which can be confusing both for programmers and for code analysis algorithms -- again obstructing experimentation with compilers and language semantics. In the few cases where identifier macros are useful, it is again better to relegate them to a library.
The proposed R6 draft materials are almost four times as long as the R5 report: That's scary in its own right, the more so because the Scheme community relies in considerable part on the efforts of individual developers, or small teams of developers, who have to implement these reports -- or who would presumably like to do so if it did not take forever. I think the Scheme community would be better served by a much smaller language, whose features included the minimum necessary so that the language could easily be extended by loading Scheme source code itself (and perhaps compiling it). In that case, implementers could concentrate on getting a small feature set correct and fast, feature-developers could work on whatever enhancements they liked, and users could use such enhancements as they chose. Perhaps the community would eventually settle on a standard group of libraries for common use (though not everyone would have to use them); but such a development might take a while. The current thrust of Scheme development makes me worry that the language will go the way of C++, which seems to have given rise to a large variety of mutually nearly incomprehensible C++ dialects and programming styles, and to a great deal of confusion about what the various features are supposed to do: I don't know anyone who claims to understand the entire C++ language, and I _do_ know at least one product-development team at a large computer company that will remain nameless here, who are forbidden to use certain features of C++ because they are allegedly so ill-defined that they behave substantially differently in different widely-used implementations. I don't want to see Scheme go that way, so I am voting against the R5.97 draft. -- Jay Reynolds Freeman Jay_Reynolds_Freeman@mac.com http://web.mac.com/jay_reynolds_freeman (personal web site)
------------------------------------------------------------------------------- I have explained some of my sentiment in the following post to comp.lang.scheme on 6 August 2007: > Guys come on it is not as though Schemers are a bunch of stodgy old > uptight conservative worry warts who aren't willing to experiment, is > it? > Scheme was an experiment, and the results were pretty good. > How many people get things perfect on the first try? :) It is precisely for this reason that some of us argue against standardization efforts such as R5.97RS and R6RS. We want to experiment and innovate. And the purpose of standardization is the exact opposite: to prevent experimentation and innovation. The objective of standardization *is* to get it right on the first try, to allow long term stability and interoperability, when the benefits of such outweigh the benefits of innovation. It is my opinion that the Scheme community will benefit far more from experimentation and innovation by rejecting R5.97RS/R6RS that it would from any potential for interoperability that it would afford. We are not an electric power utility. Nor are we C. I think most of the proponents of R5.97RS/R6RS confuse the desire for features in the implementation that they use with desire for standardization. R5.97RS should not be ratified as R6RS. That would be disasterous for the community. But that should not prevent anybody from experimenting with any or all of the features from R5.97RS in their favorite implementation. ------------------------------------------------------------------------------- I have explained some more of my sentiment in the following post that I have prepared for comp.lang.scheme but have not yet sent: There are fundamental flaws in your argument. I suspect that these flaws are what motivate many of those who advocate adoption of R6RS. 1. To the best of my knowledge there is only one vendor of Scheme implementations: Chez. What I mean by vendor is a person or organization that is paid by customers to maintain and develop the core of the implementation. 2. To the best of my knowledge, there is only one community-supported Scheme implementation: Guile. What I mean by community supported is that there is a sustainable community distinct from the original implementor that actively maintains and develops the core of the implementation. The vast majority of Scheme implementations are part time labors of love of a single person or a small group that includes current and former graduate students of a single person. While most such implementations are open source, none has attracted an exogenous developer community. Many/most of such efforts are motivated by the fact that such implementations are part of the implementor's research program. For them, innovation is the driving force. Satisfying a customer base is not. Almost all of us in the Scheme community would love for Scheme to catch on in the mainstream. We would love for there to be many profitable vendors selling high-quality Scheme implementations. We would love for there to be a vibrant open-source community that actively maintains and develops many high-quality Scheme implementations. And we would love for there to be a large customer base of real-world Scheme users that would create a demand for the above. Some people believe that the only factor that prevents this from happening is standardization (of a big language). Thus they advocate adoption of R6RS. I think that there is a huge body of compelling historical evidence that this belief is false. There are at least three prior efforts to standardize Lisp: Common Lisp, IS Lisp, and EuLisp. All adopted standards that were essentially supersets of the functionality of R6RS. At one time, there were numerous profitable commercial vendors of Common Lisp implementations: Symbolics, LMI, TI, Gold Hill, Chestnut Hill, Lucid, Harlequin, Franz, Xerox, MCL, ExperCommon Lisp, Star Sapphire, IBCL, ... just to name a few. (There were others that I can't remember at the moment.) And there were many noncommercial implementations actively maintained and developed either by individuals or by well funded research efforts: KCL, AKCL, GCL, CMULISP, CLISP, ... just to name a few. (Again, there were many others that I can't remember at the moment.) And there were many large mainstream companies that developed products that relied on these implementations. That marketplace demand fueled the supply. But that marketplace has essentially disappeared. Today there is only one commercial vendor: Franz. And only one active community-supported development effort: CMULISP. I find it untenable to believe that standardization of R6RS with all of its `real world' features will catalyze growth of a Scheme marketplace. What does R6RS provide that the real-world needs that is not provided by Common Lisp? (No, as much as I like call/cc and a single namespace, they do not fit the bill.) Scheme occupies a unique niche. A research niche and an educational niche. It is not a language. Not R6RS, not R5RS, not R4RS. It is an idea. Or a collection of ideas. It is a framework. It is a way of thinking. It is a mindset. All of this is embodied in an ever growing family of languages or dialects, not a single language. It is a virus. It is the ultimate programming-language virus. The cat is already out of the bag and there is no way to get it back in. Once someone gets the mindset, they can implement their own implementation, which is often a slightly different dialect. This has happened hundreds if not thousands of times over. (Probably hundreds of thousands or more if one counts all of the people doing homework for Scheme courses.) This happens for Scheme in a way that it doesn't for any other language. Scheme also has served as a testbed for innovative language ideas more than any other language, either by fueling such innovation or by adopting such innovation. I'm talking about the most major innovations of all of computer science. Things like: scoping, nondeterminism, parallelism, lazy evaluation, unification, constraint processing, stochastic computation, quantum computation, automatic differentiation, genetic programming, types, automated reasoning, ... just to name a few. Not crap like libraries, unicode, FFIs, assembler escapes, bit twiddling, module systems, case sensitivity, ... Before entertaining the standardization of a feature, I would need to see: 1. Evidence that a sizable community of people need that feature and agree on the standardized spec. I won't be convinced by mere claims that a feature is needed because many people confuse desire with need. I need to see compelling evidence of actual need. 2. Evidence that there is a need for many/most/all implementations to support that feature in the same way. Again, I won't be convinced by mere claims of such need. I need to see compelling evidence of actual need to run code unmodified in many/most/all implementations. And it must be the case that addressing all such standardization issues successfully allows such code that needs to be run in many/most/all implementations to actually do so. I.e., that there are no other limiting factors that prevent such and require code modification. I have written Scheme code many hours a day essentially every day for the past 15 years. (And I did this in other dialects of Lisp for 11 years prior to that. And I did this in other languages for 8 years prior to that.) Hundreds of thousands of lines. Much of it runs on at least two Scheme implementations: Scheme->C and Stalin. Almost all of it requires capabilities that are not standardized in R4RS, R5RS, or R6RS. Things like operating system access, file system access, network access, window-system access, camera access, microphone access, speaker access, robot arm access, and access to millions of lines of code written by many other people in many other languages. This is as real-world as it gets. R6RS does nothing to help that. My extensive experience is that I personally need nothing that R6RS adds over R4RS and many things that it doesn't add. ------------------------------------------------------------------------------- Some of my sentiment is expressed in the following post to comp.lang.scheme by David Rush on 9 August 2007: On Aug 6, 4:59 pm, Steve Schafer <st...@fenestra.com> wrote: > But if you're experimenting and innovating, then you do whatever. How > does the existence of the language standard/building code impede you? I don;t know if you recall the amount of grief given to certain high- performance Scheme implementations over their 'non-conformance' issues. Some of those idiosyncracies were a clear outgrowth of particular optimization experiments. And some of those experiments were based on very simple ideas and some on very complex ones - but the implementors were continually lambasted for not conforming to R5RS. And they even had the clearest documentation of their non- conformance! I *used* these systems heavily because I was doing some very heavy lifting with data mining jobs. I don't recall any stupider debate (except maybe #f/'()/nil :) than the ones about conformance issues - but people seem to make a big deal about it anyway. The goal in R6RS should be to make it easier to achieve conformance *and* easier to experiment without getting the pedants' backs up. A good standards document helps the documentation effort and frankly, R6RS achieves none of the goals mentioned above. There. I said it. david rush -- ...knowing I will regret this in the morning :) ------------------------------------------------------------------------------- Some of my sentiment is expressed in the following post to comp.lang.scheme by Aaron Hsu on 11 August 2007: On 2007-08-11 15:14:34 -0500, Griff <gret...@gmail.com> said: > That is what standards aim to do, make things easier. In this particular case, though, it will likely create a schism between the various scheme implementations, because it ignores the desires of parts of the community, in order to cater to some others. Scheme can't operate under the assumptions of one-size fits all, because the Scheme community is naturally already heavily invested in areas where divergence (to some degree) is encouraged. To attempt to change this outlook, by forcing everyone into one single paradigm, will mean that some Schemes are going to go for it, and others won't, so you'll end up with wider divergence than before, and portable code writing will not improve; the contrast will be greater. -- Aaron Hsu <aaron....@sacrificumdeo.net> ------------------------------------------------------------------------------- Also, I think module systems in general, for all languages, not just Scheme, and the proposed library system are really bad ideas, from a scientific and technical perspective. But discussion of that will have to wait for a technical paper.
The debate over the development and ratification of R6RS has been characterized by the minimalists on one side, who want a Scheme standard that continues the tradition of being a general, abstract, minimal yet powerful language, hewing close to the lambda calculus and the natural simplicity of Lisp; and the pragmatists on the other, who want a Scheme standard that is comprehensive and readily used in software engineering applications. These two camps may be considered the extreme endpoints of a spectrum of thought concerning Scheme and its role in the programming-language ecosystem. I daresay that I place myself much closer to the minimalist camp than the pragmatist camp, and consider the pragmatist turn that the proposed R6RS has taken to be not good for Scheme in general. Feynman once wrote, "What I cannot create I do not understand." A big part of Scheme's appeal is the fact that it is a powerful, usable language based on a very small core of abstractions, the implementation of which is easy to create and hence, easy to understand. The proposed R6RS strays from this tradition in several ways. While I welcome some additions, like bytevectors and a library system, others, such as conditions and Unicode strings, have warts resulting from arbitrary decisions, with cleaner and more general abstractions obviously struggling below the surface to get out. Perhaps worst of all, the operational semantics for the proposed R6RS is nowhere near as clean and succinct as the denotational semantics for R5RS. Considerations of their non-normativeness aside, the denotational semantics presented, in a couple of pages, a clear formalization of the basis of Scheme. Furthermore, if you are in the pragmatist camp, the proposed R6RS does not go far enough. Pragmatists want things like complete, pervasive object systems; built-in support for concurrency; and beefy standard libraries including most common OS and networking functions, having been spoilt on such features from exposure to the likes of Common Lisp, Perl, Python, C# and Java. As a pragmatic standard the proposed R6RS doesn't go nearly far enough; its benefit is mainly in political issues, as a "step in the right direction" for the Scheme community. Many of the problems that the proposed report addresses have been addressed better by SRFIs to R5RS, with which the report conflicts in subtle ways. In short, I cannot in good faith vote to ratify a standard which simultaneously breaks with the Scheme tradition to favor homogeneity and software-engineering appeal and still doesn't go far enough towards becoming a useful engineering tool. I would rather see a thousand more R5RS implementations, each subtly different in implementing extensions to the standard, than to see the standard for Scheme lose its place as an approachable but extremely general kernel upon which to construct a practical language implementation.
Scheme is not intended to be the most axiomatic language possible. For such purposes, other languages exist. Accordingly, I am not necessarily opposed to additions such as records or modules. Such additions could be very beneficial and help improve Scheme in areas where it already excels. That said, simplicity is one of Scheme's most critical features. I'm sure I will not be the only one to do this, but I will quote the first sentence of the introduction anyway: 'Programming languages should be designed not by piling feature on top of feature, but by removing the weaknesses and restrictions that make additional features appear necessary.' The addition of Unicode is not in the spirit of Scheme. If one needs Unicode, simply use an implementation with Unicode support. Scheme is a language I expect to be around for many more decades, and tying it to Unicode seems shortsighted. One feature I particularly wanted to see was records. Unfortunately, I am very unhappy with how the system turned out; it is simply far too complicated. Solid critiques of the system have been given on the mailing list and elsewhere so I won't rehash them here. There are also a number of small annoyances in the draft: I/O is too complex, partially due to Unicode; hash tables, while useful, are not necessary (after all, other equally useful data structures were not added); rules regarding things like square brackets should not exist, even in non-normative appendices; WHEN and UNLESS forms should not be specified; exceptions are an unfortunate (if understandable) addition; and so on. The current draft is far from what I'd like it to be. There is no sense in eliminating one of Scheme's most important features -- simplicity -- for the sake of things like Unicode. After all, even with such additions, much "real world" Scheme code will be far from portable given the lack of standard POSIX libraries, a standard FFI, and so forth. Scheme, thankfully, will never be the next Python. Therefore, future drafts should shift focus to refining Scheme as it is; clarifying top-level semantics is a good example. Additional features should be treated with severe skepticism. As it stands now, Scheme is an amazing pedagogical tool. It would be a shame to compromise that in any way.
A new language definition, composed by a new set of people with a new technical style, a new poitical process, and a new set of goals, is a good thing, but it needs a new name. Simply as a matter of branding I consider it confusing to recycle the 'Revised^N Report on the Algorithmic Language Scheme' title - a joke that was tired years ago, by the way - for something that is clearly not in the spirit of previous Scheme reports, much less the Algol 60 report. Public understanding of the programming language literature is bad enough - Scheme doesn't need this additional source of identity crisis. The above consideration would be sufficient reason for me to be disinclined to 'ratify.' But I'll give some other reasons why I'm not too happy with this report. Assuming that the report will represent pressure on me to change how I write programs and teach programming, I am vexed by the switch to case sensitivity. This incompatibility would require major changes to my programs, is not to my taste, and seems gratuitous. The loss of brackets as an extensibility option is also a loss. There are many technical problems with the report, none of which is in itself a reason for me to vote no, but cumulatively they tell me that either not enough time has been taken to produce a quality document, or that the process for producing drafts is not one that is likely to do so. I would be happy to evaluate the document on its own terms, but these terms are not stated clearly enough for me to know how. For example, I can't predict based on principles why assoc and memq (for example) are exiled to 'libraries' without bringing along the equally derivative append, string-for-each!, vector-map, and so on; the library system fails to delineate a kernel, which I had thought was one of its goals. As another example, why would one aim to nail down so many boundary conditions without also specifying order of argument evaluation? I could understand either aggressive underspecification or aggressive specification, but this report's in-betweenness mystifies me. I do not mean to single these issues out - there are many other puzzling aspects. Each one may have a perfectly sound explanation, but in combination they spell trouble. The rationale document is a very welcome addition, by the way. It is unfortunate that it appeared at the end of the process leading to the draft instead of the beginning. The modern Scheme community needs to work on a sustainable process for generating reports. Although the change in goals has undoubtedly required many changes to the language, and a consistent (such as it is) revision may have required making many changes in concert, the jump from R5RS to R6RS is too big for its users (implementors and other programmers) to digest all at once, and has not set a good example for R7RS. To make sure we all continue communicating and learning from one another, the revision process needs to be more open and incremental in the future, I think.
[Tired and isolated.. :-)] Scheme clearly needs some minimal extensions in order to become a generally practical programming language. It also needs some cleaning up at the base. But it has no place for creeping (or gallopping) featurism - the name Scheme should guarantee the well-thought-out, correct, in hindsight even obvious, decision. All else should go under another name, lest Scheme loses its unique appeal (= selling point). Some examples: (1) Strings always were a bit sore in Scheme, with their manifestly-typed locations. Instead of solving that, this draft adds bytevectors. Neither can contain variables in the right-hand side of a syntax rule - the kind of arbitrary restriction of which Scheme should be free. (2) The draft recognises libraries, a top-level and scripts, three variants of what is basically the same thing (see Queinnec&Padget: Modules, Macros and Lisp) - not the Scheme way. (3) Mr. Clinger's remarks on the record systems. So, by all means provide these things, but under its own (inferior) brand name.
I am voting against ratification of the draft because the language it specifies violates some of the fundamental design goals and principles which are behind Scheme's fame and respect in the circle of programming languages. The proposed language is both too complex for the user to grasp easily and too complex to implement. One of R5RS Scheme's strengths is that it can be implemented with minimal effort, merely a few days for an experienced implementor. Because of this several implementations have come into existence whose collective features cover a wide range of niches (platform, speed, size, interoperability, debuggability, ...). Among the over 50 existing Scheme implementations I believe at most 5 will have the energy to convert to the R6RS spec, and I fear that very few in the future will have the courage to embark on developing new implementations. The Scheme community will fragment and Scheme innovation will slowly die. It would be tedious to describe the detailed problems with the draft, and others have pointed out many of them. I will simply state some of the ones which are most obvious to me. 1) One of Scheme's strengths is its dynamic nature and in particular the ability to be used interactively through a REPL. The draft moves away from this by removing ``load'' and offering only a static linking model for programs. The draft does not explain how this affects program development and debugging using a REPL, which is the bread-and-butter of a large number of Scheme users. 2) Several features specified in the draft have been tested in existing implementations of Scheme insufficiently to warrant inclusion in the standard. Some features of the draft, such as the I/O system and records, are completely new and clearly suffer from feature creep. The standard is not the place to experiment. I do not think that R7RS can easily retract major features like these. A legitimate approach would be to use the SRFI process to introduce new features and APIs, to wait and see which SRFIs are adopted by users and implementors, and to standardize when there is a clear winner. For most features the last step could be skipped if the SRFI process was combined with a package repository in the spirit of Snow. This would remove the need for the whole ``Standard libraries'' document, and bring the language spec to a more palatable size. 3) The draft puts too much emphasis on performance. Is R5RS Scheme so slow that we need to introduce into the standard immutable variables, fields, and pairs? I am all for speed, but not at the expense of inconsistencies in the language design. Immutability hinders debugging and ``live-repair'', and goes against the basic design principles of Scheme: Programming languages should be designed not by piling feature on top of feature, but by removing the weaknesses and **restrictions** that make additional features appear necessary. Given that the draft requires the full numeric tower and bignums, and that fixnum and flonum types have implementation dependent ranges, I see no need to require fixnum and flonum types in the standard. They should be moved to a SRFI. 4) The syntax for libraries is just too complex. Syntax-case is overkill. This is another unfortunate instance of feature creep. Scheme needs a simple module system that can be grasped easily. Scheme can live with the R5RS hygienic macros for a while still.
The gap between R5RS and the proposed R6RS is simply too big. R6RS would make Scheme a different language, which is particularly unfortunate because there would be alternatives. (Just for the record: I am also opposed to Unicode in symbols for reasons that I will not outline here, because I could live with it, if the larger issue outlined below would be resolved.) The principal reason for my ``no'' vote is entirely contained in the first sentence of the introduction to every Scheme Report I have read so far: ``Programming languages should be designed not by piling feature on top of feature, but by removing the weaknesses and restrictions that make additional features appear necessary.'' R6RS contradicts this principle by including a lot of features in the language itself. Many of these features are certainly necessary in a ``real-world'' programming language, but these features are included at the cost of simplicity and orthogonality. They are included arbitrarily and not by applying the principle outlined at the beginning of the Scheme Reports. Of course, many of these features are useful and definitely should be part of the standard, but rather than arbitrarily including them in the language, the should be defined *on top of the language*. Only features that are required in order to support the libraries should be carefully added to the language itself. This approach would lead to a ``core language'' and a set of ``extension libraries'' that is implemented in terms of the core language. These libraries should be optional extensions to the core language. This has been done before, for example in Standard ML and ANS Forth. This approach has several advantages: - More libraries could easily be added at a later time without having to revise the core language too frequently. - Implementors could decide which libraries they want to include and which they want to omit. - Libraries would be exchangeable between implementation, allowing users of pure core languages implementations to use libraries of other implementors. - Reference implementations could be included in the report or supplied as supplementary material. The simplicity and elegance of Scheme has always attracted researchers and teachers who were searching for a small, well-defined language. By splitting the standard into the ``core language'' and a set of libraries, the beauty of the language could be preserved *without* restricting its use to research and education. People who want a small language could just use the core, and people who want a big language could use the libraries. Everybody wins, nobody loses. I think that this is a chance that should not be passed up. CONCLUSION R5.97RS contains a lot of very, very good ideas. I am not really opposed to any specific part of it (with the exception of Unicode in symbols). It is the sum of its parts which leaves me no other choice than a ``no'' vote. If the library part of R5.97RS was optional, and the language part would be modelled in order to support the new libraries, I would have voted ``yes''. In case R5.97RS will not be adopted, please split the language into a small and elegant core language and a set of optional extension libraries, preferably implemented in the core language itself. I know that modelling the core language would be some hard work, but the reward would be a language that is both small and elegant and ready for real-world programming at the same time.
I am voting against the adoption of the R6RS draft candidate. It mouths the words: Programming languages should be designed not by piling feature on top of feature, but by removing the weaknesses and restrictions that make additional features appear necessary. Scheme demonstrates that a very small number of rules for forming expressions, with no restrictions on how they are composed, suffice to form a practical and efficient programming language that is flexible enough to support most of the major programming paradigms in use today. but fails to honor them. The innovations of the draft fall into essentially two pieces. The first is a syntax for defining and importing identifiers from "top-level libraries". The second is the addition, through the library mechanism, of a variety of data types and attendant functional and/or syntactic interfaces. While both of these are useful for general programming, I do not believe either of them deserve a place in the Scheme language standard. Finally, the draft utterly neglects the notions of "top-level program" and "top-level environment", which are absolutely fundamental to Scheme as a language and a system. Scheme historically embodies the implementation of the definitional interpreters of Reynolds using the CPS transform. A major theme in the development of Scheme and its compilation was that the inefficient implementation of procedures in languages of the time were due to being overly committed to particular representations of control and environments. Reducing the number of control constructs to one, lambda, his compiler was free to choose any advantageous local representation of control it could find. The treatment of data manipulation was minimal in the original language, as these primitives were punted to the implementation language, MacLisp. Steele stated in his RABBIT dissertation, "We have no new ideas to present here on such issues, and so have avoid this area entirely." While the subsequent revisions of the Report on Scheme have specified support for specific data types and attendant functional interfaces, they have also lacked support for low-level data type specification, allowing implementations to punt such questions to "lower-level" implementation languages. This neglect is unfortunate, as it plays against the (efficient) metacircular definability of Scheme. Scheme is not so much a language in the usual sense as a commitment to providing a certain kind of continuation semantics. This fact is evident in R5RS's refusal to make the core syntactic keywords immutable in the top-level environment. Regrettably, the R6RS draft candidate and its library-driven programming model effectively abandons this concept. Indeed, far too much of the draft appears fixated on defining and punishing syntactic errors. Instead of the approach taken by the R6RS draft candidate, the Schemey method would be to define generic mechanisms for implementing libraries and data types. One set of candidates might be: * a safe way of specifying the layout of data structures down to the bit, * a generic way of introducing distinct namespaces into a running system and providing linkage into other namespaces, * extending the continuation model to communicating processes, and * defining program properties guaranteeing no dynamic memory allocation (similar to the tail-recursion guarantee). Having these mechanisms in the core language would allow the efficient implementation of the current R6RS proposal in Scheme as opposed to requiring a separate implementation language. I do not have specifics for these mechanisms, but then I do not believe an R6RS is necessary in the short-term. Scheme is best understood as a challenge to efficiently implement semantics that were thought to be inherently inefficient, and its revisions should always add fresh challenges.
I believe Scheme is best served by retaining its jewel-like character: tiny, beautiful and perfect. There is no need to expand Scheme as the editors propose -- if I want Common Lisp, I know where to find it. I favor only a very small expansion of Scheme to add a module system that enables numerous other extensions to be added without conflict. I like most of the proposals about numbers, because they specify dark corners where current systems may differ. But I do not believe the full numeric tower should be required, because some small and specialized implementations of Scheme may find that the full numeric tower conflicts with their other priorities. I do not like the adoption of unicode. There are competing character sets that may be preferable in some circumstances, and requiring unicode would forestall their use. Unicode necessarily requires more storage space than ascii, and more complicated runtime support, which may not be desirable in all cases. If unicode is to be introduced to Scheme, it should be done by way of a command-line switch that defaults to ascii. Both the numeric tower and unicode are instances of what I see as a larger problem -- the proposal mandates too much. The editors seem to be concerned that there is too much variety in the Scheme world, and propose to eliminate it by making the rulebook thicker. That is exactly the wrong approach. Celebrate the variety, and encourage it, so that Scheme implementations can make their own decisions about what is important to them. One of the problems with making a standard too large is that it leads to 'hardening of the arteries.' Once something becomes part of the standard, it can be hard to change -- for instance, consider the difficulty of changing the boolean-ness (is that a word) of '() several years ago. By making the new standard too large (whether you call it the language standard or the library standard really doesn't matter), you make a whole bunch of decisions that can't be changed, because changing them would break too many things. It is much better to define a small language standard, and let the SRFI process develop new libraries, which can be adopted or not as they fit the needs of users. Another problem caused by a large standard is stagnation, as has happened in the Common Lisp world, where the standard is aging and there is no motion toward a new standard. I prefer to keep the standard small. I suggest that the only change needed for a new Scheme standard (other than tightening some currently-underspecified corners of the standard, particularly with regard to numbers) is a simple module system that permits users to extend their Scheme systems cleanly. The module system should do for macros what lambda does for functions: permit macros to be visible only within a limited portion of a program. There is no need for the complicated module system the editors propose, and especially not for built-in versioning. Things that can be easily added given a module system should be excluded from the proposal. For instance, SRFIs currently provide both records and errors, so there is no need to put them in the proposal. All of the standard libraries should also be excluded from the proposal -- let implementers propose new libraries via SRFIs, and the Scheme community can choose which it prefers. In addition to these technical matters, I am also concerned about the reaction of the Scheme community. During the work of the committee, four editors resigned, and in his voting statement, a non-editor implementer pleads with voters to reject the proposal. It would be a disaster if the proposed standard causes outright schism in the Scheme community, and given the number of passionate objectors, that seems at least possible and perhaps likely. I ask the editors to retain Scheme's jewel-like properties: fix the few underspecified holes in the current standard, add a simple module system that permits clean inclusion of libraries (including macros), and let the Scheme community grow its own extensions via SRFIs.
They are some good things in draft 5.97, but we can't say it follows the caution used by previous committees. This time, committee members felt they had to resign during the review process. Implementors felt their criticisms were not heard. De facto standard SRFIs were ignored and replaced arbitrarily. Features with unnecessary complexity (e.g. Records, Syntactic Layer) were added when people didn't ask for it. Draft 5.97 should be trimmed down to a document that raises concensus. More features can be added in future RnRS if needed.
I would like to first thank the Editors of the current draft report, their past and present contributions to the Scheme community are significant and much appreciated. Thanks also to the Steering Committee for their efforts in making this process possible. The language described in the R5.97RS draft is powerful, complete, and relatively unambiguous. It extends R5RS to provide the user with more features, and clarifies certain areas of the language where R5RS implementations tend to differ. I believe that many of the goals from this draft to make the language implementations more predictable have been achieved. The current draft report, however, has imposed far more restrictions on the Scheme implementation than R5RS, which I believe will limit the implementor's freedom to experiment within a conforming system. The numerical tower, module/library system, exceptions, and Unicode characters are examples of this. The current draft makes huge strides in the direction of unifying Scheme implementations by way of imposing such restrictions, which I believe is moving the language too far in a single report. It is a marked departure from previous reports, which carries with it the risk of fragmenting the Scheme community. The reason I have voted against the ratification of the current draft is because I believe that the spirit of the Scheme language has not been preserved.
This is a constructive 'No'. Language design is such a subtle and difficult process that I wouldn't naively expect the draft to converge into something that everybody agrees on. However, the discussions on 5.9x draft did yield better drafts (in my opinion) for each iteration. Even on the controversial features where multiple mutually-exclusive ideas compete, it is good for R6RS to choose either way, at least knowing that some of us agreed to disagree. However, some suggestions and formal comments are not considered not because of a conscious design choice but because of the lack of time to change the draft to meet the deadline of the ratification draft; some because of the discussion being active too late, some because of the change in the draft is made in the last minutes. It would be regrettable if something becomes a standard because ``we didn't have time to come up with a better one by the last couple of days''. Of course we can't discuss forever. I believe, though, a few more rounds of discussions concentrating on the details would make much better R6RS.
The R6RS proposal attempts changes far beyond the spirit of Scheme that has always attracted me. The proposed language is complicated far beyond the original intent of Scheme, its description thrice the upper bound of fifty pages set by one of its inventors. It imposes restrictions on implementation design that impede future development of the language outside the three or four main implementations in the authors' minds, in the areas of numbers, text manipulation & Unicode, and the module system. Overspecification in the proposal is abundant. Portable code is hindered by the overreach of the module system's definition, which could have been designed to coexist peacefully with other systems, but which was not. This is not the definition of Scheme that I first found, and that I want to see; call it something else, but not Scheme.
The editors and steering committee have given us several reasons to vote against ratification. Two reasons are procedural: (1) Although the editors were "encouraged to record electronic discussions and meeting minutes in a publicly readable archive", they have apparently refused to make those archives public for the nine and a half months between 12 September 2006 and the present; (2) as described at greater length below, the editors made substantive technical changes in the candidate draft, including two new paragraphs of tendentious nonsense; these last-minute changes had the effect, whether intended or not, of exempting those changes from meaningful technical review, thereby forcing the registered voters to choose between ratification of a nonsensical R6RS and what some would happily misinterpret as rejection of the entire process. There is substantial risk that this candidate draft will be ratified, which means this may be my only opportunity to attach comments to my vote. I will therefore begin with a statement I had drafted when I believed the candidate draft might be worthy of ratification. * * * [Although the editors' addition of a last-minute show-stopper obsoleted the argument made below, I am including this extraneous apology because it explains why I feel the R6RS process was worth a try, even though it has not yet succeeded. This apology may also convey some sense of my disappointment with the candidate draft we were asked to ratify.] Were I voting against ratification of the R6RS, the rules would have required me to apologize for my vote. Since I am voting in favor, it seems only fair to apologize for that too. A negative vote would have been easier to explain. To explain a negative vote, it would be enough to pick any of the things I dislike about the proposed R6RS and to say it is my reason for voting against. To explain my positive vote, I must explain why none of the many things I dislike about the R6RS are show-stoppers, list some positive benefits of the R6RS, and explain why I think those benefits would leave us better off with the R6RS than without it. When evaluating the R6RS, I look at it as a programmer who has written, is maintaining, and wants to write more portable programs and libraries in Scheme. Since I am also an implementor of Scheme, I understand the burden of implementing the proposed R6RS, but that burden falls on a small number of implementors and will be amortized across the far larger number of programmers who use Scheme to write portable programs and reusable libraries. Even if the R6RS were so difficult to implement that only one out of five implementations would ever be upgraded, well, so be it; we do not really need 65 different implementations of Scheme. Had we but 10 R6RS-compatible implementations, we could write Scheme programs that are far more portable than is possible now with the 65. The proposed R6RS offers improvement in several areas where absent or weak or incompatible standards have been making it unnecessarily difficult to write portable programs and libraries. Ratification of the R6RS would improve the portability of lexical syntax, libraries, arithmetic, error reporting, Unicode characters and strings, records, binary and transcoded i/o, file querying and deletion, non-hygienic macros, and hash tables. The R6RS would also provide standard libraries for sorting; for bytevectors, which are substantially more compact than vectors for some purposes and may assist with development of more portable interfaces to libraries written in other languages; and fixnum, flonum, and bitwise arithmetic, which many programmers do not need but will help to make certain kinds of applications run much faster. The proposed R6RS also has many flaws, but we can work around most of those flaws and could even repair some of them in a future report. As to why these flaws have not already been repaired, well, my personal opinion is that I was outvoted. Furthermore, I do not believe the current editors are likely to change their collective minds with respect to the flaws that bother me, just as I am unlikely to change my putative mind on other flaws that may bother them. My list of the R6RS's flaws would amount to a list of dissenting opinions. Every editor, indeed everyone who considers the R6RS, would come up with a different list of its flaws. By contrast, its improvements are more objective: hardly anyone will deny that ratifying and adopting the R6RS would improve portability in the ways I listed earlier---although some would prefer to improve portability by other means, and a few might prefer not to improve portability at all. The objective nature of its improvements and the subjective nature of its flaws persuaded me to vote in favor of the R6RS. It was not an easy decision. * * * [The essay that follows was sent to r6rs-discuss@r6rs.org on Tue Jul 10 06:52:31 2007. I have edited one sentence for the sole purpose of avoiding a software bug that led the official archive of that mailing list to truncate my essay.] an essay on language design: fixing the syntactic record layer Introduction ============ More than twenty years have passed since I wrote this [1]: Programming languages should be designed not by piling feature on top of feature, but by removing the weaknesses and restrictions that make additional features appear necessary. Scheme demonstrates that a very small number of rules for forming expressions, with no restrictions on how they are composed, suffice to form a practical and efficient programming language that is flexible enough to support most of the major programming paradigms in use today. I still believe that first sentence, and I still believe Scheme ought to demonstrate what is claimed in the second sentence, but the draft we are being asked to ratify does not always do that. This shortcoming of the candidate draft can be seen in the modularity and interoperability problems that beset the syntactic and procedural record layers. As I will show, these problems are caused by artificial restrictions that have been imposed upon the syntactic layer. Removing those weaknesses would remove the problems. A last-minute change in the 5.97 draft attempted to fix things by piling yet another feature, a parent-rtd clause, on top of the syntactic layer [2]. The presumed purpose of that parent-rtd clause was to address Andre van Tonder's observation that incompatibilities between the syntactic and procedural record layers create a modularity problem: You cannot define a new record type that inherits from an existing record type without knowing whether the base type was defined by the syntactic or by the procedural layer [3,4]. That also implies that record definitions are brittle: Unless a record type is sealed, its definition cannot be changed from using the syntactic layer to using the procedural layer, or vice versa, without breaking all record types that inherit from it. Although the editors acted with the best of intentions, their addition of the parent-rtd clause did not solve the problems it was intended to solve. Even with the parent-rtd feature, you *still* have to know whether the base record type was defined using the syntactic or record layer, and you *still* can't change a record definition from one layer to the other without running the risk of breaking client code. To make matters worse, the 5.97 draft added a couple of questionable statements that attempt to excuse the interoperability problems while asserting privileged status for the draft's syntactic layer. One of those statements is based upon a patently false claim. The editors have submitted this draft to the Steering Committee as a candidate for ratification, so there is no meaningful technical review of these last-minute changes apart from the ratification vote itself. Abstract ======== I will summarize the interoperability problems mandated by library chapter 8 of the 5.97 draft, trace them to their root cause, show how they could easily be fixed by removing artificial restrictions that are imposed by the syntactic layer, and conclude by showing that the two exculpatory statements of that chapter are partly false and thoroughly misleading. Symptoms ======== That the syntactic and procedural record layers do not interoperate well has been known for a while now, and had been acknowledged by the editors, who had declared their intention not to do anything about it [5]. I did not consider that to be an absolute barrier to ratification, because better syntactic layers would have been proposed as SRFIs, and one of those alternatives might eventually have replaced the R6RS syntactic layer. That would have been a better outcome than piling on still more features without fixing the fundamental problem. The last-minute addition of parent-rtd addressed the most obvious of the interoperability problems, which was first mentioned in public by my formal comment 90 [5], but left these others in place: * Record types defined by the syntactic layer are not interchangeable with record types defined by the procedural layer. * In consequence, the code you write for a record type definition that inherits from some base type depends upon whether that base type was defined using the syntactic or procedural layer. * Both layers are complex, which makes it hard for a casual reader to understand their relationships. * The procedural layer is the more expressive layer, so the draft's new warnings that try to frighten programmers into preferring the syntactic layer would have limited impact even if they were true. The procedural layer is more expressive because it can do everything the syntactic layer can do, and it can also be used to create multiple constructor-descriptors for a single record type descriptor [6]. That, of course, is a cue for someone to jump up and say "We can fix that by adding a new clause to the syntactic layer!" Adding yet another feature would be exactly the wrong thing to do. We ought to fix the problem, not try to cover it with still more sterile adhesive strips. The proper course of action is to understand why these problems matter, why they arose, and how to fix them. Then we should fix them. The Impending Records War ========================= By specifying two barely interoperable record systems, and advocating the more complex and less expressive of the two, the 5.97 draft would create an unnecessary dilemma for organizations that use Scheme. Most will deal with incompatibilities between the two record layers as they arise. After dealing with several instances of the problem, some organizations will standardize on one or the other of the record layers. Some will choose the procedural layer, because it is more expressive or because it is more in keeping with Scheme's roots as a higher order procedural language. Others will choose the syntactic layer because that is what the 5.97 draft suggests, or because Scheme's macro system is really cool. When these organizations import code that uses the "wrong" record layer, they will rewrite it to use their organization's standard layer. When they get tired of rewriting code, they will clamor for the "wrong" record layer to be expunged from the standard. That conflict is unnecessary. We do not have to fight over which record layer is wrong, because we could fix things so both are right. That is not hard. We should do it. The Root Cause ============== The root technical problem is easy to understand. I'll digress for a few paragraphs to give you a chance to figure it out before I do. A friend of mine remarked that it is impossible to design a record system for Scheme that won't lead to interoperability problems. This is Scheme, after all. Any Scheme programmer can define a new syntactic layer for records, and its notion of a record type might be different from the standard notion, so programmers shouldn't expect to be able to define a record type that inherits from any other programmer's record type. That's true, up to a point. The point, of course, is that we should be able to define records that inherit from any record system that uses the standard notion of a record type. The 5.97 draft doesn't have a standard notion of a record type. It has *two* standard notions of a record type, with context-restricted coercions between them. That is the root technical cause of the modularity and interoperability problems. The solution is to define a single standard notion of a record type, and to use that one notion as the basis for both the syntactic and the procedural layers. To do that, of course, the standard notion of a record type will have to be a first-class object. The syntactic layer can deal with first-class values by deferring them to run time, but the procedural layer can't reach back in time to deal with macro or expand-time values. This has been a source of controversy among the editors. The 5.96 and earlier drafts fudged by saying a record type is an "expand-time or run-time description". The 5.97 draft changed that phrase to "expand-time representation of the record-type", thereby institutionalizing the interoperability problems even as it pretended to do something about them. In the 5.97 draft, the procedural layer's notion of a record type is an rtd (record type descriptor). The syntactic layer's notion of a record type is an expand-time representation that bundles an rtd with a preferred constructor-descriptor. I will now describe a straightforward solution to this muddle, based upon the following standard notion of record type: A record type is an rtd. To maintain compatibility with the syntactic layer of the 5.97 draft, and for that reason only, every non-opaque rtd will be associated with a preferred constructor-descriptor. The preferred constructor-descriptor is the one associated with the rtd in a special global table or, if that table contains no preferred constructor-descriptor for rtd, then the preferred constructor descriptor is the one computed by (make-record-constructor-descriptor rtd <parent-preferred> #f) where <parent-preferred> is the parent's preferred constructor-descriptor, or #f if there is no parent. Note that the global table is a run-time object that holds run-time constructor-descriptors. Note also that any implementors who would like to maintain an expand-time or compile-time table of (conservative approximations to) the information contained within that run-time table are welcome to do so. How does an rtd become associated with its preferred constructor-descriptor? By having the two be passed as arguments to a special procedure that is known to the macro/library/compiler/whatever system, but is not exported by any of the standard libraries. In other words, only the syntactic layer can associate an rtd with a preferred constructor-descriptor other than the default. I understand that the preferred constructor-descriptors are an ugly hack. They would not be present in any record system I would design from scratch. Why then am I proposing these preferred constructor-descriptors? Because I am taking a lesson from C++, which caught on in part because it was bug-compatible with C. The system I am about to describe is, in one of Mike Sperber's favorite phrases, a conservative extension of the 5.97 record system. That means everything that would work in the 5.97 system would work in the system I am about to describe, and a number of things that wouldn't work in the 5.97 system, but should, will indeed work in the system I describe. How do we arrange that? By removing the artificial restrictions mandated by the 5.97 draft. (We'll keep the artificial restriction that limits the procedural layer's preferred constructor-descriptors to default constructor-descriptors. That restriction would be easy to remove also, but removing it might complicate the optional expand-time or compile-time bookkeeping that appears to have been the driving force behind the 5.97 design.) Proposal ======== To avoid still more discussion of the API for the R6RS record layers, I propose we keep the syntax and almost all of the semantics of the 5.97 syntactic layer, and keep all the procedures and all the semantics of the 5.97 procedural and inspection libraries. I further propose we extend the syntactic layer by eliminating certain weaknesses and restrictions. We will: * Require define-record-type to bind the <record name> to the rtd, in the same group of definitions that binds the constructor, predicate, accessors, and mutators. * Allow the <parent rtd> and <parent cd> of a parent-rtd clause to be arbitrary expressions, as in the 5.97 draft. (Notice, however, that the <record name> bound by a define-record-type is now an ordinary variable and can serve as the <parent rtd> without having to resort to a use of record-type-descriptor). * Extend the parent clause to allow any expression, which must of course evaluate to an rtd. * Extend record-type-descriptor to allow any expression as its <record name>, provided the expression evaluates to an rtd; in other words, record-type-descriptor would become a procedure. * Extend record-constructor-descriptor to allow any expression as its <record name>, provided the expression evaluates to an rtd; it would then evaluate to the rtd's preferred constructor-descriptor. In other words, record-constructor-descriptor would become a procedure. I might have missed something, but I believe that's all it takes. Note that record-type-descriptor has become unnecessary. It is nothing more than the identity function restricted to record type descriptors. If I weren't trying to describe a conservative extension of the 5.97 draft, I would urge removal of record-type-descriptor from the language [7]. Note that both the scope and semantics of a <record name> bound by the syntactic layer have become clearer. The <record name> is no longer a name for some mysterious "expand-time representation" that is neither a run-time object nor a macro. It is now an ordinary variable that obeys ordinary scope rules, can be exported or imported in the usual way, for run time, and has a first class object as its value. I'm not going to claim this is a good record system, but it offers all the features of the 5.97 draft, all of the performance (for all use cases that can even be expressed using that draft), and none of the modularity and interoperability problems associated with the record layers of that draft. Performance =========== The 5.97 draft contains a couple of new paragraphs that attempt to justify its limitations by appeal to matters of performance. Page 16 says: However, the record operations provided through the procedural layer may be significantly less efficient than the operations provided through the syntactic layer. Therefore, alternative implementations of syntactic record-type definition [sic] should, when possible, expand into the syntatic [sic] layer rather than the procedural layer. To put that in perspective, let me point out that the map procedure may be significantly less efficient than using a do loop. Indeed, there have been many implementations of Scheme in which do loops are more efficient than calls to map. Despite that fact, none of the Scheme reports have ever advocated using do loops instead of map. To advocate such things would be inappropriate for an implementation-neutral standard. In typical uses of records, the base record type will be defined at the top level of a library, where the variable that holds the rtd will be immutable, as will all of the other top-level variables that are defined in terms of the rtd. That makes it almost as easy to optimize code written using the procedural layer as code written using the syntactic layer. Sure, some compilers may optimize one without bothering to optimize the other, but most would optimize neither or both. In any case, it is obvious that any program that can be written under the restrictions of the 5.97 draft is also a program under my proposal. If some macro expander and/or compiler were written to record some expand-time information when the syntactic layer of the 5.97 draft is used, then they can record exactly the same information for the syntactic layer of my proposal. The only additional complication of my proposal is that the macro expander and/or compiler would have to recognize when the <record name> is an expression other than a variable that was bound by define-record-type. Recognizing that is trivial. My proposal would not require any new flow analysis. The advanced optimizations that require flow analysis would use essentially the same flow analysis under my proposal as they would under the 5.97 draft. Consider, for example, that the 5.97 draft allows the rtd associated with a <record name> to escape via the record-type-descriptor syntax. That means the rtd of a <record name> that is exported by a library, whether explicitly or implicitly, may escape within some importing library [8]. Hence any optimizations that require flow analysis of the rtd must either defer the optimization until a whole-program analysis can be performed, or else assume that the rtd of an exported <record name> will flow into arbitrary contexts. In other words, the rtd-flow analysis required by the 5.97 draft is already as bad as it could be, so my proposal can't possibly make it any worse. Page 18 says: Note: Use of the parent-rtd clause generally forces an implementation to delay the generation of constructor, accessor, and mutator code until the record-type definition is evaluated at run time, since the type of the parent is not generally known until then. That is a false statement. The editors might as well claim that the code for a lambda expression cannot be generated until run time, since the values of its free variables will not be known until then. Even in the current release of Larceny, all of the code generated for constructors, accessors, and mutators is generated at compile time. None of that code is ever generated at run time. In future releases, an unoptimized record access will consist of a procedure call, a double tag check, an indirect load, an eq? check, and a load. Twobit's existing optimizations, or easy extensions of them, will eliminate any or all of that code when it is safe to so. The code that isn't eliminated by optimization will be generated at compile time. No code will ever be generated at run time. And that's for the procedural layer. There is no earthly reason for a compiler to generate worse code for the syntactic layer than for the procedural layer, or to generate it any later. The parent clause should therefore be used instead whenever possible. This recommendation is based upon a false premise. So What? ======== The substantive changes that were made in the 5.97 draft are immune to meaningful technical review, so why did I write this? Partly to blow off steam, of course, but there were at least three other reasons as well. As Andre van Tonder wrote, the only way for us to register disagreement with changes made in the 5.97 draft is to vote against ratification [9]. Under the rules of that vote, any negative vote must be accompanied by an explanation, so I had to write something like this anyway. I am told that, if this draft is not ratified, the Steering Committee intends to pay a lot of attention to the reasons cited in those explanations. If you vote against ratification for reasons that include some of the issues I have discussed, then you may be able to save some writing by citing this essay. The second reason has to do with what happens after the vote. As I see it, there are three possible outcomes: 1. The vote is negative, which would give the editors an opportunity to get it right. 2. The draft is ratified, and everyone pretends to live happily ever after. 3. The draft is ratified, and the unhappy folk design alternative syntactic layers, probably written up as SRFIs, that build upon the R6RS procedural layer. This little essay of mine might be of some use, or at least have some influence, in the event of outcomes 1 or 3. I don't think outcome 2 is stable in the long run. I think it would evolve into outcome 3. Thirdly, writing this essay gave me a chance to consider whether I still believe what I wrote so long ago. Conclusion ========== Programming languages should be designed not by piling feature on top of feature, but by removing the weaknesses and restrictions that make additional features appear necessary. R6RS Scheme should demonstrate that a very small number of rules for forming expressions, with no restrictions on how they are composed, suffice to form a practical and efficient programming language. William D Clinger 5-9 July 2007 -------- [1] Jonathan Rees and William Clinger [editors]. Revised^3 report on the algorithmic language Scheme. ACM SIGPLAN Notices 21(12), December 1986, pages 37-79. [2] Michael Sperber et al. Revised^5.97 report on the algorithmic language Scheme -- standard libraries. http://www.r6rs.org/versions/r5.97rs-lib.pdf http://www.r6rs.org/document/lib-html-5.97/r6rs-lib.html [3] Andre van Tonder. Rationale issues. Posted to r6rs-discuss, 26 June 2007. http://lists.r6rs.org/pipermail/r6rs-discuss/2007-June/002825.html [4] William D Clinger. Response to [3], 27 June 2007. http://lists.r6rs.org/pipermail/r6rs-discuss/2007-June/002889.html [5] William D Clinger. Record layers are not orthogonal. Formal comment #90, 13 November 2006. http://www.r6rs.org/formal-comments/comment-90.txt [6] It doesn't matter whether the descriptor was created using the syntactic or the procedural layer. This is an example of the interoperability we should have throughout the record system. [7] It is analogous to endianness, buffer-mode, et cetera. [8] Whether the 5.97 draft allows a <record name> to be exported from a library may not be entirely clear, but disallowing such exports would be disastrous, so I assume the 5.97 draft is meant to allow such exports. [9] Andre van Tonder. parent-rtd clauses in records. Posted to r6rs-discuss, 3 July 2007. http://lists.r6rs.org/pipermail/r6rs-discuss/2007-July/003071.html * * * [These final paragraphs were sent to r6rs-discuss@r6rs.org on Tue Jul 24 15:28:07 EDT 2007. I have edited the first sentence.] It now appears that the primary technical basis for the two paragraphs of tendentious nonsense on pages 16 and 18 consists of two load instructions that fetch the free variables of a closure. Furthermore one of those load instructions is easily eliminated for almost all record accesses even with the procedural layer, and the other is just as hard to remove with the syntactic as with the procedural. I can accept poor language design. I cannot accept false and misleading attempts to excuse poor language design or to discourage programmers from using closures. If the editors wish to advocate nonsense, they should do so in their individual publications, not in the R6RS. Will