17.1 Module Languages

► |  | The Racket Guide

1 | Welcome to Racket
2 | Racket Essentials
3 | Built-In Datatypes
4 | Expressions and Definitions
5 | Programmer-Defined Datatypes
6 | Modules
7 | Contracts
8 | Input and Output
9 | Regular Expressions
10 | Exceptions and Control
11 | Iterations and Comprehensions
12 | Pattern Matching
13 | Classes and Objects
14 | Units
15 | Reflection and Dynamic Evaluation
16 | Macros
17 | Creating Languages
18 | Concurrency and Synchronization
19 | Performance
20 | Parallelism
21 | Running and Creating Executables
22 | More Libraries
23 | Dialects of Racket and Scheme
24 | Command-Line Tools and Your Editor of Choice
| Bibliography
| Index

▼ | 17 | Creating Languages

17.1 | Module Languages
17.2 | Reader Extensions
17.3 | Defining new #lang Languages

► | 17.1 | Module Languages

17.1.1 | Implicit Form Bindings
17.1.2 | Using #lang s-exp

On this page:

17.1.1 Implicit Form Bindings
17.1.2 Using #lang s-exp

Racket
top contents ← prev up next →

### 17.1 Module Languages🔗ℹ

When using the longhand module form for writing modules, the module path that is specified after the new module’s name provides the initial imports for the module. Since the initial-import module determines even the most basic bindings that are available in a module’s body, such as require, the initial import can be called a module language.

The most common module languages are racket or racket/base, but you can define your own module language by defining a suitable module. For example, using provide subforms like all-from-out, except-out, and rename-out, you can add, remove, or rename bindings from racket to produce a module language that is a variant of racket:

> > > The module Form introduces the longhand module form.

> > (module raquet racket
> (provide (except-out (all-from-out racket) lambda)
> (rename-out [lambda function])))
> > (module score 'raquet
> (map (function (points) (case points
> [(0) "love"] [(1) "fifteen"]
> [(2) "thirty"] [(3) "forty"]))
> (list 0 2)))
> > (require 'score)
> '("love" "thirty")

#### 17.1.1 Implicit Form Bindings🔗ℹ

If you try to remove too much from racket in defining your own module language, then the resulting module will no longer work right as a module language:

> > (module just-lambda racket
> (provide lambda))
> > (module identity 'just-lambda
> (lambda (x) x))
> eval:2:0: module: no #%module-begin binding in the module's
> language
> in: (module identity (quote just-lambda) (lambda (x) x))

The #%module-begin form is an implicit form that wraps the body of a module. It must be provided by a module that is to be used as module language:

> > (module just-lambda racket
> (provide lambda #%module-begin))
> > (module identity 'just-lambda
> (lambda (x) x))
> > (require 'identity)
> #<procedure>

The other implicit forms provided by racket/base are #%app for function calls, #%datum for literals, and #%top for identifiers that have no binding:

> > (module just-lambda racket
> (provide lambda #%module-begin
> ; ten needs these, too:
> #%app #%datum))
> > (module ten 'just-lambda
> ((lambda (x) x) 10))
> > (require 'ten)
> 10

Implicit forms such as #%app can be used explicitly in a module, but they exist mainly to allow a module language to restrict or change the meaning of implicit uses. For example, a lambda-calculus module language might restrict functions to a single argument, restrict function calls to supply a single argument, restrict the module body to a single expression, disallow literals, and treat unbound identifiers as uninterpreted symbols:

> > (module lambda-calculus racket
> (provide (rename-out [1-arg-lambda lambda]
> [1-arg-app #%app]
> [1-form-module-begin #%module-begin]
> [no-literals #%datum]
> [unbound-as-quoted #%top]))
> (define-syntax-rule (1-arg-lambda (x) expr)
> (lambda (x) expr))
> (define-syntax-rule (1-arg-app e1 e2)
> (#%app e1 e2))
> (define-syntax-rule (1-form-module-begin e)
> (#%module-begin e))
> (define-syntax (no-literals stx)
> (raise-syntax-error #f "no" stx))
> (define-syntax-rule (unbound-as-quoted . id)
> 'id))
> > (module ok 'lambda-calculus
> ((lambda (x) (x z))
> (lambda (y) y)))
> > (require 'ok)
> 'z
> > (module not-ok 'lambda-calculus
> (lambda (x y) x))
> eval:4:0: lambda: use does not match pattern: (lambda (x)
> expr)
> in: (lambda (x y) x)
> > (module not-ok 'lambda-calculus
> (lambda (x) x)
> (lambda (y) (y y)))
> eval:5:0: #%module-begin: use does not match pattern:
> (#%module-begin e)
> in: (#%module-begin (lambda (x) x) (lambda (y) (y y)))
> > (module not-ok 'lambda-calculus
> (lambda (x) (x x x)))
> eval:6:0: #%app: use does not match pattern: (#%app e1 e2)
> in: (#%app x x x)
> > (module not-ok 'lambda-calculus
> 10)
> eval:7:0: #%datum: no
> in: (#%datum . 10)

Module languages rarely redefine #%app, #%datum, and #%top, but redefining #%module-begin is more frequently useful. For example, when using modules to construct descriptions of HTML pages where a description is exported from the module as page, an alternate #%module-begin can help eliminate provide and quasiquoting boilerplate, as in "html.rkt":

> > "html.rkt"

> > > #lang racket
> > > (require racket/date)
> > > (provide (except-out (all-from-out racket)
> > > #%module-begin)
> > > (rename-out [module-begin #%module-begin])
> > > now)
> > > (define-syntax-rule (module-begin expr ...)
> > > (#%module-begin
> > > (define page `(html expr ...))
> > > (provide page)))
> > > (define (now)
> > > (parameterize ([date-display-format 'iso-8601])
> > > (date->string (seconds->date (current-seconds)))))

Using the "html.rkt" module language, a simple web page can be described without having to explicitly define or export page and starting in quasiquoted mode instead of expression mode:

> > (module lady-with-the-spinning-head "html.rkt"
> (title "Queen of Diamonds")
> (p "Updated: " ,(now)))
> > (require 'lady-with-the-spinning-head)
> > page
> '(html (title "Queen of Diamonds") (p "Updated: " "2026-02-21"))

#### 17.1.2 Using #lang s-exp🔗ℹ

Implementing a language at the level of #lang is more complex than declaring a single module, because #lang lets programmers control several different facets of a language. The s-exp language, however, acts as a kind of meta-language for using a module language with the #lang shorthand:

> #lang s-exp module-name
> form ...

is the same as

> (module name module-name
> form ...)

where name is derived from the source file containing the #lang program. The name s-exp is short for “S-expression,” which is a traditional name for Racket’s reader-level lexical conventions: parentheses, identifiers, numbers, double-quoted strings with certain backslash escapes, and so on.

Using #lang s-exp, the lady-with-the-spinning-head example from before can be written more compactly as:

> #lang s-exp "html.rkt"
> (title "Queen of Diamonds")
> (p "Updated: " ,(now))

Later in this guide, Defining new #lang Languages explains how to define your own #lang language, but first we explain how you can write reader-level extensions to Racket.

top contents ← prev up next →