On this page:
top
up

17.1Module LanguagesπŸ”— i

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 raquetracket
(rename-out [lambda function])))
> (module score'raquet
(map (function(points)(case points
[(0)"love"][(1)"fifteen"]
[(2)"thirty"][(3)"forty"]))
(list 02)))
> (require 'score)

'("love" "thirty")

17.1.1Implicit Form BindingsπŸ”— i

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-lambdaracket
> (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-lambdaracket
> (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-lambdaracket
;ten needs these, too:
> (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-calculusracket
(provide (rename-out [1-arg-lambdalambda ]
[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-appe1e2)
(#%app e1e2))
(define-syntax-rule (1-form-module-begine)
(define-syntax (no-literalsstx)
(raise-syntax-error #f"no"stx))
(define-syntax-rule (unbound-as-quoted. id)
'id))
> (module ok'lambda-calculus
((lambda (x)(xz))
(lambda (y)y)))
> (require 'ok)

'z

> (module not-ok'lambda-calculus
(lambda (xy)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)(yy)))

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)(xxx)))

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"

(require racket/date)
(rename-out [module-begin#%module-begin ])
now)
(define-syntax-rule (module-beginexpr... )
(define page`(htmlexpr...))
(provide page)))
(define (now)

Using the "html.rkt" module language, a simple web page can be described without having to explicitly define or export page and starting in quasiquote d 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: " "2025-08-16"))

17.1.2Using #lang s-exp πŸ”— i

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 namemodule-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
up

AltStyle γ«γ‚ˆγ£γ¦ε€‰ζ›γ•γ‚ŒγŸγƒšγƒΌγ‚Έ (->γ‚ͺγƒͺγ‚ΈγƒŠγƒ«) /