On this page:
19.1 Topics Covered
19.2 Extending Embedded Languages
19.3 Good Bye
7.4.0.4

19 Closure

Matthias Felleisen

19.1 Topics Covered

The focus of this week has been language-oriented programming (LOP) or the design of various kinds of languages. We did not teach ordinary Racket programming. Again, “design” means “using tools to create abstractions as systematically as possible.” It does not refer to the vague word that language designers often use for the careful development of syntax and the haphazard assignment of semantics.

LOP is a range of ideas, all of which build on one central mechanism in Racket:

language extension via define-syntax

With language extension, we can then realize a number of things:

kind of language

     

when covered

module-level languages

     

Modules, Macros, Languages, More Language Variations

     

Typed Languages with Turnstile

fine-grained embedded languages

     

Two Techniques, Extended Lab Regexps

extensible embedded languages

     

see below

To get you started, we presented you with a rough model of macro expansion (Language-Oriented Programming):
  • reading (turning char sequences into syntax trees)

  • hooking functions-at-syntax-time into the expander

  • expanding a syntax tree until no nodes refer to macros

From then on, we focused on the language extension and language building:
  • techniques for writing new macros:

  • techniques for raising the level of abstraction:

    • various flavors of syntax classes

  • lexical scope and preserving it by default:

    • lexical scope of the underlying language

    • lexical scope as the default for macros (textual substitution breaks all of this)

    • breaking lexical scope with datum->syntax

  • different lexical scope with parameters

  • building a module-level language in Racket

    • modules can export and import macros

    • the language is the first import and it provides the meaning for everything in foo for (module name language-name foo)

    • in particular, the language must define #%module-begin, which determines the meaning of the rest of the module

    • there are more interposition points: #%app, #%top, #%datum

  • with #lang languages we can build languages from scratch, restrict existing languages, extend one, and do all of the above.

  • build typed module languages

  • build simple expression-level embedded languages.

19.2 Extending Embedded Languages

At this point, you might think that Racket has solved all problems of language-oriented programming but this is not the case. Much remains to be done.

Over the years, we have time and again encountered situations where embedded languages, such as the one you worked on this morning, themselves call for syntactic extensibility. We constructed those capabilities on an ad hoc basis:

  • On Monday morning, we briefly showed our way of extending the language of match patterns. See Extending match.

  • Matthew used a good bit of the embedded language of providing and requiring across module boundaries. See provide Macros and require Macros for the documentation on how to extend those languages.

  • As you may know, Racket comes with a web server that has an embedded language for dispatching from requests to places in the web server’s world. See Extending web-server/dispatch for ways of extending this DSL.

Turnstile in some ways fits this pattern, too, but it also differs from the above.

Then again, you have seen embedded languages or even built some that you might wish to extend syntactically and you can’t:

Building syntactic extensibility into an embedded domain-specific language is non-trivial. We can do it but our tools for doing so are not ready for prime time. In a year from now or so, they will be. And then you will be more than welcome to attend a RacketSchool again and learn all about.

19.3 Good Bye

Racket School Exit Survey