What it’s about
Notes that while some languages gave you the ability for cute notation (C) and others allowed experimentation with domain specific languages (Lisp/Scheme), Racket has evolved to the point where the user can actually contribute extensions to the language that are indistinguishable from the core language features. Specifically, it is about the Racket language extension API.
What it contributes
The paper notes that it has been a trend for a while now for language creators and enthusiasts to try to design or take advantage of environments that could add benefits or features to the languages which they loved. Some examples of these were the Java Virtual Machine and .NET CLR that offered a rich set of features to languages that could be built on top of them. There are many examples of languages trying to target these existing frameworks, however the platform they are targeting is merely that - a platform - and will not allow them to continue to grow the language. The result of this is the experimentation in design of these languages on these platforms is expensive and labor intensive.
What is needed is a host language that supports linguistic re-use, or in other words the host language should be able to reuse the scoping mechanisms, namespace management, etc... of the host language. This style of design makes language extensions just libraries that supplement the existing compiler.
This paper presents Typed Racket as an example of how language extension should be supported. An important point they highlight to supporting this ability is the existence of syntax objects - this allows more well defined and powerful conversions of syntax rather than merely utilizing textual matching as other, simpler systems do.
What’s amazing as you get into this paper is to think about what has happened with the development of this macro system and what it now supports. Type systems obviously have uses and benefits (optimizations, for example) however Racket is not a statically-typed language. Low and behold, however, a simple series of libraries, as described as Typed Racket is introduced, allows not only macros that allow type annotations to be added to identifiers, functions, etc... but additionally provides more complex features that allow typed and untyped modules to interact in a very natural way. This powerful manner to extend Racket and allow this Typed version to be created also allows the Typed version to not be hamstrung by not having available the masses of libraries that have been developed thus far, rather the macro system is powerful enough to support the algorithmic notions to allow these existing libraries and new typed modules to work together in harmony. Pretty amazing stuff. One would think if they were developing a “typed” version of a language they would be starting from scratch almost across the board.
As mentioned, one of the benefits/contributions of the typing system (and thus of the macro system, right?) is the ability to optimize to a degree previously not possible in the dynamically typed world of racket. In Racket type checks must be performed, for instance, before things can be added (+a b) since it is only valid to add numbers or other similarly numeric types. In typed Racket, a and b would be typed and this run-time check would be gone. More in depth, lower level optimizations can take place as well when the compiler can make valid assumptions about the kind of data it will be working with. This is done via a type-driven optimization pass after type checking is complete. Fascinating - Racket, in the kernel, is still an untyped language, so these optimizations must be macros that expand these type assuming calculations into operations that take advantage of unsafe type-specialized primitives. Thus utilization of unsafe, optimized primitives is, of course, done in macros through rewrite rules. As seen from the various results for comparing run times, these type-based optimizations can have a significant impact on run time.
Questions
- When would you use typed racket? For optimizations primarily? (That seemed to be a big highlight of this paper)
- Are there any other languages that have added a robust type system? Or had an optional one? (I guess one that compares in some way to Typed-Racket/Racket, since none have probably done it via macro language extensions since... no other language has the umph to do that)