11 KiB
Module Syntax
The #lang
at the start of a module file begins a shorthand for a
module
form, much like '
is a shorthand for a quote
form. Unlike
'
, the #lang
shorthand does not work well in a REPL, in part because
it must be terminated by an end-of-file, but also because the longhand
expansion of #lang
depends on the name of the enclosing file.
1. The module
Form
The longhand form of a module declaration, which works in a REPL as well as a file, is
(module name-id initial-module-path
decl ...)
where the name-id
is a name for the module, initial-module-path
is
an initial import, and each decl
is an import, export, definition, or
expression. In the case of a file, name-id
normally matches the name
of the containing file, minus its directory path or file extension, but
name-id
is ignored when the module is require
d through its file’s
path.
The initial-module-path
is needed because even the require
form must
be imported for further use in the module body. In other words, the
initial-module-path
import bootstraps the syntax that is available in
the body. The most commonly used initial-module-path
is racket
,
which supplies most of the bindings described in this guide, including
require
, define
, and provide
. Another commonly used
initial-module-path
is racket/base
, which provides less
functionality, but still much of the most commonly needed functions and
syntax.
For example, the "cake.rkt"
example of the previous section could be
written as
(module cake racket
(provide print-cake)
(define (print-cake n)
(show " ~a " n #\.)
(show " .-~a-. " n #\|)
(show " | ~a | " n #\space)
(show "---~a---" n #\-))
(define (show fmt n ch)
(printf fmt (make-string n ch))
(newline)))
Furthermore, this module
form can be evaluated in a REPL to declare a
cake
module that is not associated with any file. To refer to such an
unassociated module, quote the module name:
Examples:
> (require 'cake)
> (print-cake 3)
...
.-|||-.
| |
---------
Declaring a module does not immediately evaluate the body definitions
and expressions of the module. The module must be explicitly require
d
at the top level to trigger evaluation. After evaluation is triggered
once, later require
s do not re-evaluate the module body.
Examples:
> (module hi racket
(printf "Hello\n"))
> (require 'hi)
Hello
> (require 'hi)
2. The #lang
Shorthand
The body of a #lang
shorthand has no specific syntax, because the
syntax is determined by the language name that follows #lang
.
In the case of #lang
racket
, the syntax is
#lang racket
decl ...
which reads the same as
(module name racket
decl ...)
where name
is derived from the name of the file that contains the
#lang
form.
The #lang
racket/base
form has the same syntax as #lang
racket
,
except that the longhand expansion uses racket/base
instead of
racket
. The #lang
scribble/manual
form, in contrast, has a
completely different syntax that doesn’t even look like Racket, and
which we do not attempt to describe in this guide.
Unless otherwise specified, a module that is documented as a “language”
using the #lang
notation will expand to module
in the same way as
#lang
racket
. The documented language name can be used directly with
module
or require
, too.
3. Submodules
A module
form can be nested within a module, in which case the nested
module
form declares a submodule. Submodules can be referenced
directly by the enclosing module using a quoted name. The following
example prints "Tony"
by importing tiger
from the zoo
submodule:
"park.rkt"
#lang racket
(module zoo racket
(provide tiger)
(define tiger "Tony"))
(require 'zoo)
tiger
Running a module does not necessarily run its submodules. In the above
example, running "park.rkt"
runs its submodule zoo
only because the
"park.rkt"
module require
s the zoo
submodule. Otherwise, a module
and each of its submodules can be run independently. Furthermore, if
"park.rkt"
is compiled to a bytecode file via `raco make`
, then
the code for "park.rkt"
or the code for zoo
can be loaded
independently.
Submodules can be nested within submodules, and a submodule can be referenced directly by a module other than its enclosing module by using a submodule path.
A module*
form is similar to a nested module
form:
(module* name-id initial-module-path-or-#f
decl ...)
The module*
form differs from module
in that it inverts the
possibilities for reference between the submodule and enclosing module:
-
A submodule declared with
module
can berequire
d by its enclosing module, but the submodule cannotrequire
the enclosing module or lexically reference the enclosing module’s bindings. -
A submodule declared with
module*
canrequire
its enclosing module, but the enclosing module cannotrequire
the submodule.
In addition, a module*
form can specify #f
in place of an
initial-module-path
, in which case the submodule sees all of the
enclosing module’s bindings—including bindings that are not exported via
provide
.
One use of submodules declared with module*
and #f
is to export
additional bindings through a submodule that are not normally exported
from the module:
"cake.rkt"
#lang racket
(provide print-cake)
(define (print-cake n)
(show " ~a " n #\.)
(show " .-~a-. " n #\|)
(show " | ~a | " n #\space)
(show "---~a---" n #\-))
(define (show fmt n ch)
(printf fmt (make-string n ch))
(newline))
(module* extras #f
(provide show))
In this revised "cake.rkt"
module, show
is not imported by a module
that uses (require "cake.rkt")
, since most clients of "cake.rkt"
will not want the extra function. A module can require the extra
submodule using (require (submod "cake.rkt" extras))
to access the
otherwise hidden show
function.See submodule paths for more
information on submod
.
4. Main and Test Submodules
The following variant of "cake.rkt"
includes a main
submodule that
calls print-cake
:
"cake.rkt"
#lang racket
(define (print-cake n)
(show " ~a " n #\.)
(show " .-~a-. " n #\|)
(show " | ~a | " n #\space)
(show "---~a---" n #\-))
(define (show fmt n ch)
(printf fmt (make-string n ch))
(newline))
(module* main #f
(print-cake 10))
Running a module does not run its module*
-defined submodules.
Nevertheless, running the above module via racket
or DrRacket prints a
cake with 10 candles, because the main
submodule is a special case.
When a module is provided as a program name to the racket
executable
or run directly within DrRacket, if the module has a main
submodule,
the main
submodule is run after its enclosing module. Declaring a
main
submodule thus specifies extra actions to be performed when a
module is run directly, instead of require
d as a library within a
larger program.
A main
submodule does not have to be declared with module*
. If the
main
module does not need to use bindings from its enclosing module,
it can be declared with module
. More commonly, main
is declared
using module+
:
(module+ name-id
decl ...)
A submodule declared with module+
is like one declared with module*
using #f
as its initial-module-path
. In addition, multiple
module+
forms can specify the same submodule name, in which case the
bodies of the module+
forms are combined to create a single submodule.
The combining behavior of module+
is particularly useful for defining
a test
submodule, which can be conveniently run using raco test
in
much the same way that main
is conveniently run with racket
. For
example, the following "physics.rkt"
module exports drop
and
to-energy
functions, and it defines a test
module to hold unit
tests:
"physics.rkt"
#lang racket
(module+ test
(require rackunit)
(define ε 1e-10))
(provide drop
to-energy)
(define (drop t)
(* 1/2 9.8 t t))
(module+ test
(check-= (drop 0) 0 ε)
(check-= (drop 10) 490 ε))
(define (to-energy m)
(* m (expt 299792458.0 2)))
(module+ test
(check-= (to-energy 0) 0 ε)
(check-= (to-energy 1) 9e+16 1e+15))
Importing "physics.rkt"
into a larger program does not run the drop
and to-energy
tests—or even trigger the loading of the test code, if
the module is compiled—but running raco test physics.rkt
at a command
line runs the tests.
The above "physics.rkt"
module is equivalent to using module*
:
"physics.rkt"
#lang racket
(provide drop
to-energy)
(define (drop t)
(* 1/2 49/5 t t))
(define (to-energy m)
(* m (expt 299792458 2)))
(module* test #f
(require rackunit)
(define ε 1e-10)
(check-= (drop 0) 0 ε)
(check-= (drop 10) 490 ε)
(check-= (to-energy 0) 0 ε)
(check-= (to-energy 1) 9e+16 1e+15))
Using module+
instead of module*
allows tests to be interleaved with
function definitions.
The combining behavior of module+
is also sometimes helpful for a
main
module. Even when combining is not needed, (module+ main ....)
is preferred as it is more readable than (module* main #f ....)
.