Saturday, April 23, 2011

First Draft of R7RS For The Small Language

As I recounted in my Two Schemes post, the Scheme Steering Committee decided to split Scheme into large and small languages and formed working groups for each. The small language working group has just published their draft R7RS for the small language. I've read over the draft and am very pleased with it. At 67 pages it remains small and concise and, in fact, it retains the flavor of R5RS as promised.

So what's different? There's a complete list of changes at the end of the draft, and also in the post announcing the draft, but here are some that appealed to me:

  • Modules are now part of the language definition. This is important because it was one of the major sources of incompatibilities between different implementations.
  • Records à la SRFI 9 are now included as part of the language.
  • Parameters, sort of like dynamic variables from Common Lisp, are introduced as global variables that can be safely dynamically rebound. Objects such as current-input-port, current-output-port, and the newly introduced current-error-port are defined as parameters.
  • Blobs, homogeneous vectors of integers in the range [0..255], are a new disjoint type. This is to allow Scheme to better handle binary data. Ports can now be defined as character or binary.
  • letrec* is now part of the language and internal defines are specified in terms of it.
  • case now supports a ‘=>’ syntax analogous to cond's.
  • case-lambda is now part of the base library as a way of dispatching on the number of arguments.
  • string-map, string-for-each, vector-map, and vector-for-each round out the sequence operations.
  • Character escaping in strings is expanded.
  • Case folding in the reader is configurable with no folding as the default. Generally I don't care about this because I alway use lower case anyway and don't understand why anyone would do otherwise. As an Emacs user I already do enough chording without worrying about capital letters. Still, it does raise an issue: as soon as Louis Reasoner sees that case matters he starts using really ugly camel case identifiers like GeeIWishIWereCodingTheWindowsKernel. Now Louis is welcome to do whatever he likes as long as I can ignore it, which I can if there is case folding. Of course, once Louis gets used to case mattering, we get stuff like
    (define sum-odds
      (lambda (lst)
        (define SUM-ODDS
          (lambda (lst result)
            (if (null? lst)
                (if (odd? (car lst))
                    (SUM-ODDS (cdr lst) (+ (car lst) result))
                    (SUM-ODDS (cdr lst) result)))))
        (SUM-ODDS lst 0)))

    Mostly, I just wish this issue would magically go away. Or better yet that people would be sensible in their coding conventions.

  • No Unicode support is required but the set of characters used by an implementation are required to be consistent with the latest Unicode standard to the extent that the implementation supports Unicode.

Most of this is already in R6RS—indeed, what isn't in R6RS—and almost all of it can be added by the user. For example, we've all written code like

(define string-map
  (lambda (f str)
    (list->string (map f (string->list str)))))

as a quick and dirty string-map but now we have a, presumably, more robust version that handles multiple strings. Even the reference implementation of parameters can be done at the user level—this is, after all, one of the strengths of Scheme. What's nice is not a lot of the work is done for us—well, OK, that is nice—but that these things are now standardized and portable. There's more than I've mentioned here so be sure to checkout the draft itself or at least the list of changes from R5RS.

I'm looking forward to the large language R7RS draft. It will be interesting to see if the working group does indeed manage to produce the “happier outcome” that the steering committee promised.

No comments:

Post a Comment