Do racket macros have more advanced functionality than those found in Scheme or Common Lisp? I suspect so, especially regarding modules, namespaces and scoping, etc, but I'd appreciate a simple rundown of what Racket macros can do, if anything, that other lisps can not.
Additionally, Scheme/CL also expose the reader layer to the developer, and using this, is it not possible in those lisps to create entirely new languages (not just s-expr macros), such as Scribble, the way you can in Racket?
In other words, is Racket simply a philosophy/convention around "language oriented programming" with convenient syntactic wrappers to this end, or does it more fundamentally extend Scheme to do things technically impossible in that language?
Thanks a lot.
Racket is a fork of Scheme, the simple language at the core of this course for many years. Scheme was created primarily as an experiment in understanding how programming languages work. Racket retains its basic favor, but it also adds many, many features that make the language useful in the 21st century.
Conversely, not understanding hygiene can make Racket macros seem confusing and mysterious. But they are not. Hygiene is the answer to a simple question: a macro generates code that gets deposited elsewhere.
A macro is a syntactic form with an associated transformer that expands the original form into existing forms. To put it another way, a macro is an extension to the Racket compiler. Most of the syntactic forms of racket/base and racket are actually macros that expand into a small set of core constructs.
Racket is a descendant of Scheme, which in turn is a descendant of Lisp. So while Racket is not Lisp (in the specific Common Lisp sense), it is a Lisp (in the familial sense). Its core ideas—and core virtues—are shared with Lisp. So talking about Racket means talking about Lisp.
Two key features that make "language-oriented programming" work in Racket are:
The first bullet is basically what #lang
does. Having the module system be in charge of setting up the reader and the bindings available in a given module allows the easy use of different languages. Without this, it'd be more cumbersome to work with languages like Scribble or at-exp
.
The second is that Racket provides overrideable context-sensitive macros such as #%app
, #%module-begin
, and so on that allow customization of, say, every function application within a module or of the entire module. This allows adding, for example, a type-checking pass over the entire module.
This isn't an exhaustive list of features that help build languages in Racket. If you're interested in reading more about it, the "Languages as Libraries" paper is worth reading.
I'll recommend reading the paper "Composable and Compilable Macros - You Want it When?" by Matthew Flatt.
It explains how macros and modules work together in Racket.
Then implement a small language in Racket - say TinyBasic. Then compare with the other languages.
UPDATE
http://www.cs.utah.edu/plt/publications/jfp12-draft-fcdf.pdf
See also Matthew's reply for the same question after @Scott posted it on the list, with a more recent overview paper.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With