The Beauty of Scheme


Let me preface this blog post: it does not explain much about Scheme itself through examples, but just expands on some of my thoughts on the language. Pretty soon I will start writing coding posts.

Sometimes I feel the need to defend the merits of the Scheme language because there are many deficiencies:

  • It has a small standard library, and has lacked a way of importing libraries for a long time. Sometimes you must reinvent the wheel. R6RS and R7RS try to improve the situation here but it's a work in progress.
  • There are many incompatible implementations, with no standard implementation. This results in the fragmentation of an already-small community.
  • It has a strange syntax, being a Lisp-derivative, and is even more parenthesis-heavy than Common Lisp and Clojure. It does not have traditional syntax for mathematical operations.
  • Scheme is a multi-paradigm language, except that it does not have built-in support for object-oriented programming and lacks built-in functional features like lazy evaluation and persistent data structures. In that sense, Scheme is actually less "elegant" than Smalltalk or Haskell, which are languages that go all the way with a single paradigm.
  • External libraries are basically able to implement full object-oriented semantics, but there is no compatibility between various object systems. In my perfect world, YASOS would be standardized as the Scheme object system.
  • Scheme has a long-standing history of use in academia, and nearly zero usage in the commercial software industry. I have no doubt that there are individuals and organizations that incorporate Scheme into there code, but there are no obvious "success stories" or commercial support for Scheme. Smalltalk is not a widely used language, but it is strongly positioned because of its commercial history.

The list goes on, but these are the basic problems with Scheme. In my opinion, no particular problem is insurmountable for the language, but the difficulty may leave the reader scratching their head and thinking: "Why bother? Just use Python." In my opinion, there's nothing wrong with Python, Java, C++, etc. at a fundamental level. I just happen to like Scheme bit more and want to see it succeed.

There's definitely a sentimental aspect to it for me, because I like seeing a small community blossom rather than latching onto an established one. That's just my personality getting in the way, though. If you want to get things done, just use Python or something.

On the other hand, I do think Scheme has some secret strengths that these other languages lack. Most of the following points have largely been covered by other Schemers and Lispers in the past, but perhaps not with this exact perspective.

Scheme: The Good Parts

Scheme has the following nice properties:

  • Scheme is minimalist and has a clean design. Even R6RS, which had backlash for being too complex, is a standard less than 100 pages.
  • Scheme is Lisp-derived. Much of the syntax can be written as macros of simpler forms, enhancing the previous point.
  • Scheme is (relatively) easy to implement. More importantly, it has a culture of reimplementing the language and therefore a large number of implementations.
  • Scheme is multi-paradigm. Although it supports functional idioms, Scheme is not against mutation, alleviating the need for heavyweight persistent data structures.

I think it's pretty clear that all of these points are closely related, and point to a singular strength of Scheme that cannot be easily summarized. Other languages share one or more of these points, but Scheme is really one-of-a-kind in how far it goes with the idea.

Minimalist

Scheme is minimalist in its design, although that was not a goal of the original designers (Guy L. Steele and Gerald Jay Sussman). It just so happens that closures are really powerful enough to easily express many other structures like iteration and polymorphism.

Lisp-derived

In addition to closures, Scheme also achieves additional minimalism (or is that subtractional?) through hygienic macros, enabled by its Lisp-derived syntax. Ironically, hygienic macros are probably the most technically complicated idea in Scheme and is often a feature implemented last by novices.

I won't go into detail about how hygienic macros work, but the practical impact of being a Lisp-derived language is that there is no fundamental syntax in Scheme. Variable declaration, variable assignment, procedure calls, binary operators, are all reduced to the abstract syntax tree and simple transformations of it.

Many implementations

A result of being minimalist is that Scheme has a large number of implementations -- in my estimate, more than any other language if we include any implementation R4RS compliant or later (and still about ten implementations and counting if we stick to R7RS-small). This is both design influenced and cultural: it's considered a pretty normal thing for a Schemer to go ahead and implement their own if they feel like it! Javascript, Smalltalk, Python, etc. lack this cultural aspect (partly because they are more complex to implement). If nothing else, this is the most unique thing about Scheme and is the basic reason why I don't find anything else directly comparable.

Why does any of this matter?

I've talked a lot about why this stuff is cool, but not why it really matters. There's a central concept here, which I will try to summarize like this:

Scheme is unique because it's a language that can be kept entirely in your head. That includes both the interface and implementation of the language.

Scheme isn't 100% unique in that regard -- Smalltalk has elements of it (although doesn't have the ease of implementation part of it), and Forth probably goes even further. However, I feel Scheme is easier to use that Forth.

In terms of the practical benefit of this, I haven't figured it out yet. It's clearly good from a teaching perspective, which is why it was used in SICP, but it's not obviously important to an engineer.

Winning Big

I don't expect Scheme to be as popular as C or Python, but I do wish it were taken more seriously as a language in its own right. Basically I am aiming for the positioning of Smalltalk at the moment: more or less a niche, but still having a number of "success stories" in the commercial software industry. Racket or Chez seem like the best candidates to me (and indeed, Racket may switch to a Chez backend soon).

How can Scheme do that? There's no easy way, so I'll just keep programming my own little libraries and applications in Scheme until the day comes. I do see a couple of possibilities, but it's a bit out of reach. Guile Emacs would potentially invite a large number of neophytes, and it would be the first time Scheme really made headlines since SICP. It would be pretty rad, even if it didn't propel Scheme into ubiquity. However, although Guile is being actively developed (and thankfully have decided that R7RS is worth it), Guile Emacs seems pretty distant -- maybe a decade away.

Ultimately, I do get the impression that we are growing as a community even though I have not hard numbers to back that up. We will have to see what happens in the coming years.