crumbles.blog computers are bad and you shouldn’t use them

Scheme Reports at Fifty: Where do we go from here?

Based on my talk at the Scheme Workshop 2025. You might prefer to have me talk it at you instead.

We are holding an election to the Scheme Steering Committee. Register to vote and nominate candidates!


In December this year, the Scheme reports will turn fifty. As chair of the working group entrusted with the next major revision of the report, I want to start a discussion in the Scheme community about what a good Scheme report looks like in 2025, and how it’s different from what it looked like in 1975, and from other times when the Scheme report was revised.

Who is the Scheme report for?

When making any document, we have to consider who we’re writing for, how they’re going to use it, and what they want and need from it in order to do their thing. For the Scheme report, the obvious two groups are users and implementers. These are very vague groupings, and like any attempt to divide up a group as large and diverse as the Scheme user base, one can’t at all pretend like every member of these groupings has the same views on every issue. Nonetheless, a rule of thumb is that users want their pet features added, creating pressure to grow the report;1 implementers want to be able to actually create a compiler, creating pressure to keep the report smaller and simpler. But there are also clear subdivisions where even this clear breakdown falls apart, like in the embedded space, where both users and implementers want something that can work on limited-resource environments.

Another tension still rarely recognized is between users in education – students learning the language – and long-time Schemers who know it very well. The How to Design Programs approach seems to have worked for many more beginning students than Structure and Interpretation of Computer Programs ever did, because HtDP acknowledges from the start that assuming brand new students will be able to learn with a tool designed for people who are already experts means that tool can’t be as helpful to those just finding their feet in a new way of thinking.

But in Scheme we often get into philosophical and even political debates when we talk about what the Scheme report should be like; debates which have much more to do with an ideological belief about the nature of the language than with the direct, practical needs of the debaters.2

Big and little languages

A classic such argument is over whether certain versions of Scheme – usually R6RS, and sometimes also the one that my working group is producing – are ‘too big’. On the other hand, Scheme reports that don’t have this quality can be seen as being too ‘little’ for doing real programming work in.

Earlier, littler Scheme reports are often described by the makers of these arguments as a ‘diamond-like jewel’, or similar. The ‘diamond-like jewel’ wording is, I think, from the infamous ‘Worse is Better’ section of Richard P. Gabriel’s paper ‘Lisp: Good News, Bad News, and How to Win Big’.

In 1998 Guy L. Steele, co-inventor of Scheme, read a keynote paper at OOPSLA entitled ‘Growing a Language’ (transcript). In the paper, he talks a lot about the tension between the qualities of a big language vs a little language, and in particular talks about Scheme, saying:

Could not “The Right Thing” be a small language, not hard to port but with no warts?

I guess it could be done, but I, for one, am not that smart (or have not had that much luck). But in fact I think it can not be done. Five-and-twenty years ago, when users did not want that much from a programming language, one could try. Scheme was my best shot at it.

But users will not now with glad cries glom on to a language that gives them no more than what Scheme or Pascal gave them. They need to paint bits, lines, and boxes on the screen in hues bright and wild; they need to talk to printers and servers through the net; they need to load code on the fly; they need their programs to work with other code they don’t trust; they need to run code in many threads and on many machines; they need to deal with text and sayings in all the world’s languages. A small programming language just won’t cut it.

From the things he names as examples of what users want to do with languages, it’s clear that Steele’s mind was very much on Java, and Java in 1998 at that. Some of these things just aren’t in fashion any more: some were thought to be good ideas at the time, but now seen as bad ideas; some of them just never caught on. But some of them are just as important as ever.

Of the things that are just as important as ever, though, many of those no longer seem like things a language should have to take care of; they are, rather, the province of third-party libraries.

That, in fact, is how Steele concludes ‘Growing a Language’: users should be able to grow the language itself by adding libraries.

But, it seems, the base of Scheme as it was in 1975, and even in 1998, was not enough. Most people today would agree that a programming language without even a standard error-handling mechanism is quite deficient, even if it does give one the ability to build one for oneself.

And, in fact, most Schemers agree that the best way for Scheme to go forward is to find better ways for Scheme users to grow the language. Our disagreement, then, is not about ‘bigness’ per se, but where the bigness comes from. Few would swallow a thousand-page Scheme report; setting aside the actual labour of designing and implementing it, most people would be perfectly content with using their own personal library of language extensions whose documentation would run to a thousand pages if it were all documented.3 Our disagreement is over how big the base needs to be in order to provide a foundation to grow from; and over what needs to be in the foundation, to enable users to give themselves this bigness.

Dynamic systems, static languages

So big vs little is one axis of disagreement within the Scheme community. How about another?

In 2012 Richard P. Gabriel wrote an essay paper, ‘The Structure of a Programming Language Revolution’. He talks about how he took a break from programming languages in the early 1990s in order to do a fine arts degree. When he came back in the late 1990s, everything had changed. When he left, people in programming languages talked about dynamic, evolving systems like Common Lisp and Smalltalk. By the time he returned, the conversation had changed to static languages like Haskell.

I think one of the other axes of division in the Scheme community is around this matter, and the reason is that our community lived through this paradigm shift without, collectively, noticing it. Some of the community moved on to the new paradigm; others continued to think in terms of the old.4 The two sides do not understand one another’s concerns.

The dynamic systems viewpoint is epitomized by the R5RS, whose only entrypoint for programs is the interactive top level, and which even began to lay the groundwork for a library and namespacing system that would have been based on first-class environments and the eval procedure. Implementations which follow the dynamic systems model include MIT Scheme and Guile.

The static languages viewpoint is epitomized by the R6RS, which doesn’t have an interactive top level at all. Implementations which adhere to this model include Chez, Racket, and Loko, but also niche implementations like Stalin which don’t have their own interactive top level at all.

Put briefly, the dynamic languages people see Scheme as a dynamic language, plain and simple, and want to be able to do all the run-time modification that they should be able to do in any such language. The static languages people see Scheme as a static language in all regards except its type system.

And yet more

Already with these two dimensions of belief about what kind of language Scheme is – big vs little, static vs dynamic – we have a huge range of potential expectations for what the Scheme report might be like. When we compare these viewpoints in terms of the models their advocates might prefer to take as guidance for the future development of the language, we can see just how far apart these ideas are.

Those who want a little, dynamic language will look to earlier versions of the report, and maybe to the cores of languages like Lua and JavaScript. A little static language might look like SML. Common Lisp might be a model to follow for a big dynamic language, or Haskell for a big static language. I’ve seen almost every one of these languages used to suggest what a suitable future direction for Scheme might look like.

These are hugely different rôle models to follow – and these are only two matters on which people have different feelings. I could add more for more philosophical disagreements about the nature of Scheme, ideas about what the right way to make and publish a Scheme report should be, and even very specific individual language features. Clearly, we can’t satisfy all of these expectations at once.

Does a Scheme report still make sense?

Given these deep divisions over the essential nature of the Scheme language, does it even make sense that we still keep making a Scheme report?

‘No’ is an entirely possible answer to this question. Already in the R6RS and R7RS small days, people were arguing that Scheme standardization should stop.

If we went this way then, just like Racket in its default mode no longer claims to be a Scheme report implementation, Schemes would slowly diverge into different languages. Guile Scheme would one day simply be Guile; Chicken Scheme would be Chicken, and so on. Like the many descendants of Algol 60 and 68, and the many dialects of those descendants, each of these languages would have a strongly recognizable common ancestor, but each would still be distinct and, ultimately, likely incompatible.

It shouldn’t surprise you that I don’t think this is the way to go. As a user of Scheme, I can still see ways I want to extend the common core of all of these implementations. It’s much better to be able to do this once and have my extension available on many implementations, than to have to work hard to port my extension to multiple different languages. All implementations benefit by agreeing on a common core that works to be able to grow the language.

Racket is already a cautionary tale. It has some amazing features, but those of us on other implementations can’t take advantage of them because Racket’s implementations of those features aren’t portable. Even Guile has this problem, because it’s still culturally normal among users of that implementation to use its own define-module declaration instead of the standard R6RS or R7RS library or define-library, even if your code only uses standard Scheme features and maybe some common SRFIs. There’s much Guile code I’d like to use on Chez for more speed, or on Chibi for a smaller implementation footprint, that currently requires at least some porting effort for not much good reason.

This is more or less the same rationale for Scheme reports that there has always been, and I think it continues to apply today.

R6RS and R7RS small considered more alike than widely believed

So our thoughts must naturally turn to unification. The co-existence and incompatibility of R6RS and R7RS small have become emblematic of the splits in our community. The R6RS editors and community are, to some extent, justified in feeling that R7RS small unfairly abandoned their work. But in fact the two are more similar than is widely recognized, and in many cases the design of R7RS small in fact vindicates the decisions of the R6RS editors.

This may seem a shocking claim about a division which some predicted would end up killing Scheme as a programming language. But, I think, WG1 stumbled their way towards a realization, which I’ll get to just below, which led them to a develop a library system working on basically the same model as R6RS. R7RS small library declarations support conditional compilation and other features which, in R6RS, is exclusively the province of the ‘main’ level language; but once all the cond-expands in define-library are dealt with, the two are essentially the same. R7RS small’s define-library declarations can be compiled entirely ahead of time to R6RS’s library style – there is already a program which does this, Akku.

Between 2007 and 2013 the landscape of programming tools also shifted so some of the things which were criticized in R6RS’s day – bytevectors for binary data, and Unicode throughout – now seem perfectly normal. It now seems wrong for a programming language not to support these. R7RS small also adopted, for example, the same exception raising and handling mechanism as R6RS.5

The changing landscape of programming tools around Scheme means that programmers now have a much different sense of the ‘littleness’ of a language than in 2007. Since Rust there’s increasing recognition that memory safety should be treated as non-optional even in most low-level programming, and is cheap to implement; it now seems strange that R5RS and below, and R7RS small, make bounds violations undefined behaviour in the C sense.6

Moreover, what R7RS small’s authors seemed to realize is that the report will always be a minimum, and not a maximum. I think this is why, although it came from a group of users who started out highly critical of the R6RS for its static model of libraries and programs, R7RS small adopted essentially that model. It doesn’t restrict implementations from providing more dynamic library features.

The small/large report split helps even more, because now the report offers two different minimums for implementations to choose from, according to what their needs are. The minimum for ‘the practical needs of mainstream software development’ is, as Guy Steele says, much bigger than it used to be, and that’s fine!

Join, or die

This is my appeal to the Scheme community, then. If we don’t have a Scheme report that the majority of implementations and users accept, Scheme as a coherent single language will simply die. Not all implementations – it’ll be like if, as above, we stopped making Scheme reports and everyone went their own way. But even the implementations which survived would clearly be weaker for not being able to share the libraries of the others.

R7RS is our best shot at joining together to still be able to share code with one another, and to grow the language together – not only in the report itself, but much more in the tools we build with it.

The sacred craft

Joining, however, means compromising.

Nobody will look at any Scheme report and say it is perfect. I can’t look at any version of the report, not even R5RS, and say it was a ‘diamond-like jewel’.7 Even if it were perfect for one person, it cannot be all things to all people. Scheme has historically been too shy of compromise; the uncompromising pursuit of perfection, even though perfection is a quality nobody will ever agree on, may be why we have struggled so much to move onwards while other languages have not.

‘Compromise’ is a dirty word for some people, but I would like to offer another perspective. Although R7RS is sometimes perceived as anti-R6RS, two of the small report’s editors actually voted in favour of R6RS ratification.8 One of them, John Cowan – also my predecessor as chair of WG2 for the large language – wrote in the rationale to his vote:

a well-crafted compromise is in my opinion the most sacred thing that a secular age knows

We may not be able to have a diamond-like jewel, but we can have the most sacred thing a secular age can make.


As mentioned at the top, I hope this essay will really open a conversation about these matters. You can write a comment on Mastodon, or if that’s too limiting, on the Scheme Reports mailing list.

And don’t forget the election to the Scheme Steering Committee!


  1. 26 people who voted against R6RS ratification said, in some form of words, that the language was too big; 13 people said they wanted specific new features and voted against because they weren’t there. Despite the apparent contradiction, the latter group overlaps with the former almost completely.↩︎

  2. Ideology is not bad; I do not use the word to impugn anyone or their arguments. Without ideology, we have no structure with which to build our understanding of the world around us. I have my own ideology of Scheme as much as anyone in the community.↩︎

  3. We may also need to set aside that only the person who wrote such a library would want to actually use it or any software written with it. Today we are also happy to shop in the free market of language extensions, choosing our own personal favourite design of pattern matcher or HTML templater out of many that have already been written by other people.↩︎

  4. As an example of the kind of new work that came out of the Scheme community which didn’t make sense under the old paradigm but seems vital under the new, consider that it was only in 2002 that Matthew Flatt came out with ‘Composable and Compilable Macros: You Want it When?, introducing phasing as a model of compile-time evaluation compatible with static ahead-of-time compilation. This problem only began to be considered by Schemers in the 1990s, because the problem itself doesn’t really make sense under the dynamic, evolving systems paradigm.↩︎

  5. Although the R7RS small authors didn’t seem to understand what raise-continuable was for and didn’t include an analogous construct to the non-&serious condition types of R6RS.↩︎

  6. My (least) favourite example is that it isn’t safe to decode UTF-8 text from an untrusted source in R7RS small, because invalid UTF-8 passed to utf8->string is also undefined behaviour. Anal monkeys galore.↩︎

  7. What kind of diamond has undefined behaviour when you try and write beyond the end of a buffer? Does diamond-like perfection in a language inherently demand diamond-like perfection of the programs written in it?↩︎

  8. Another WG1 member, Aaron Hsu, voted against R6RS ratification, but if one looks at his WG1 proposals and votes, later consistently pushed to adopt things from R6RS within WG1.↩︎


Comments

Post your comment by replying to this post on Mastodon.