Every Racket source file begins with a #lang line. (#lang is pronounced hash-lang.)
The #lang line specifies what language should be used to interpret the source code in the file.
There can be only one #lang line per source file. It’s always the first line of code (though it can be preceded by whitespace or comments).
Most often, the simple #lang name notation is used to invoke a language, for instance:
1 2 3 4 5 6 | #lang br #lang br/quicklang #lang racket/base #lang pollen/pre #lang datalog #lang scribble/manual |
Dialects of languages are typically notated with slashes (e.g., br vs. br/quicklang). (Not all languages have dialects—consult the documentation to see which are supported.)
This shorthand #lang name notation only works with languages that have been installed as part of a Racket package. Alternatively, you can use the #lang reader path syntax to specify a local path to a language reader, which can be useful for quick prototypes:
1 | #lang reader "path/to/language-reader.rkt" |
Or with #lang s-exp path, you can use Racket’s default S-expression reader with an arbitrary expander:
1 | #lang s-exp "path/to/language-expander.rkt" |
More broadly, the #lang line supports metalanguages that can be chained with another language to add new features. For instance, the three language specifications below all rely on racket/base for the heavy lifting, but the second and third get extra features from the at-exp and debug metalanguages, respectively:
1 2 3 | #lang racket/base #lang at-exp racket/base #lang debug racket/base |
Under the hood, the #lang line works by discovering the reader for the language, which is a Racket function. Racket passes all the source code after the #lang line to the reader function, which returns code describing a module. Racket then replaces the source code with this new module code, and evaluation continues from there.
Logical minds might infer that because a #lang line invokes a reader, and the reader returns syntax for a module expression, then every source file that starts with a #lang line will end up with a single module expression at the top level. Yes—this is exactly right.
In fact, every Racket source file consists of a single module expression at the top level. This is why in Racket lingo, a source file is also known as a module.
Thus, even though the #lang line is highly idiomatic, it’s not technically required. In a Racket source file, you can always use a module expression instead of a #lang line. In practice, there’s no reason to do this, but we can use this to demystify what’s happening.
These two programs are the same, and will both print 42:
1 2 | #lang racket/base (* 6 7) |
This program is different, however:
It doesn’t print 42 because the #lang line introduces its own module wrapping, so you end up with nested modules like so:
Though Racket automatically evaluates the top-level module, it doesn’t automatically evaluate nested modules, so submod-name never runs.
Caution: in the above examples, you could easily convert to module form because racket/base source code uses Racket’s standard S-expression reader. But in general, a module expression standing alone can’t invoke a special reader. So even though this would be valid Scribble code:
1 2 | #lang scribble/text The product is @(* 6 7). |
You can’t do this:
More broadly, this means you can’t mix different readers within a single source file. There can be only one #lang line, and it determines the reader for the whole file.
Anything on the #lang line that follows the name of the main language is treated as part of the source code. So this prints 42:
1 | #lang br (* 6 7) |
You can put Racket-style comments before the #lang line, so this also prints 42:
1 2 3 4 5 | ;; line comment #| block comment |# #;(commented expression) #lang br (* 6 7) |
Racket has no officially sanctioned way of passing configuration arguments to a language on the #lang line (maybe someday—it would be useful). Certain languages like scribble/doclang2 support things that look like keyword arguments. But in fact, these arguments are part of the source code, and are being handled specially by the language’s read-syntax function.
1 2 3 4 5 | #lang scribble/doclang2 #:id doc #:post-process values #:exprs () "Hello world" |
Modules explainer
The #lang Shorthand in the Racket Guide