more doc updates for submodules

This commit is contained in:
Matthew Flatt 2012-03-08 14:51:13 -07:00
parent 54a441c0e3
commit a6a1b02de5
5 changed files with 161 additions and 7 deletions

View File

@ -52,8 +52,8 @@ racket
The relative reference @racket["cake.rkt"] in the import
@racket[(require "cake.rkt")] works if the @filepath{cake.rkt} and
@filepath{random-cake.rkt} modules are in the same
directory. (Unix-style relative paths are used for relative module
references on all platforms, much like relative URLs in HTML pages.)
directory. Unix-style relative paths are used for relative module
references on all platforms, much like relative URLs in HTML pages.
@; ----------------------------------------
@section[#:tag "module-org"]{Organizing Modules}

View File

@ -207,3 +207,47 @@ and it should @italic{not} be used when a plain, portable
The automatic @filepath{.ss} and @filepath{.rkt} conversions apply as
with other forms.}
@; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@specsubform/subs[#:literals (submod)
(submod base element ...+)
([base module-path
"."]
[element id
".."])]{
Refers to a submodule of @racket[base]. The sequence of
@racket[element]s within @racket[submod] specify a path of submodule
names to reach the final submodule.
@examples[
(module zoo racket
(module monkey-house racket
(provide monkey)
(define monkey "Curious George")))
(require (submod 'zoo monkey-house))
monkey
]
Using @racket["."] as @racket[base] within @racket[submod] stands for the
enclosing module. When a path of the form @racket[(#,(racket quote)
id)] refers to a submodule, it is equivalent to @racket[(submod "."
id)].
Using @racket[".."] as an @racket[element] cancels one submodule step, effectively
referring to the enclosing module. For example, @racket[(submod "." "..")]
refers to the enclosing module of the submodule in which the path
appears.
@examples[
(module zoo racket
(module monkey-house racket
(provide monkey)
(define monkey "Curious George"))
(module crocodile-house racket
(require (submod "." ".." monkey-house))
(provide dinner)
(define dinner monkey)))
(require (submod 'zoo crocodile-house))
dinner
]}

View File

@ -26,13 +26,15 @@ The longhand form of a module declaration, which works in a
where the @racket[_name-id] is a name for the module,
@racket[_initial-module-path] is an initial import, and each
@racket[_decl] is an import, export, definition, or expression. In
the case of a file, @racket[_name-id] must match the name of the
containing file, minus its directory path or file extension.
the case of a file, @racket[_name-id] normally matches the name of the
containing file, minus its directory path or file extension, but
@racket[_name-id] is ignored when the module is @racket[require]d
through its file's path.
The @racket[_initial-module-path] is needed because even the
@racket[require] form must be imported for further use in the module
body. In other words, the @racket[_initial-module-path] import
bootstraps the syntax available in the body. The most commonly used
bootstraps the syntax that is available in the body. The most commonly used
@racket[_initial-module-path] is @racketmodname[racket], which supplies most
of the bindings described in this guide, including @racket[require],
@racket[define], and @racket[provide]. Another commonly used
@ -120,6 +122,108 @@ Unless otherwise specified, a module that is documented as a
@racketmodname[racket]. The documented language name can be used
directly with @racket[module] or @racket[require], too.
@; ----------------------------------------------------------------------
@section[#:tag "submodules"]{Submodules}
A @racket[module] form can be nested within a module, in which case
the nested @racket[module] form declares a
@deftech{submodule}. Submodules can be referenced directly by the
enclosing module using a quoted name. The following example prints
@racket["Tony"] by importing @racket[tiger] from the @racket[zoo]
submodule:
@racketmod[
#:file "park.rkt"
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 @filepath{park.rkt} runs its submodule @racket[zoo]
only because the @filepath{park.rkt} module @racket[require]s the
@racket[zoo] submodule. Otherwise, a module and each of its submodules can be run
independently. Furthermore, if @filepath{park.rkt} is compiled to a
bytecode file (via @exec{raco make}), then the code for
@filepath{park.rkt} or the code for @racket[zoo] can be loaded independently.
A @racket[module*] form is similar to a nested @racket[module] form,
but @racket[module*] inverts the possibilities for reference between
the submodule and enclosing module:
@itemlist[
@item{A submodule declared with @racket[module] can be
@racket[require]d by its enclosing module, but the submodule
cannot @racket[require] the enclosing module or lexically
reference the enclosing module's bindings.}
@item{A submodule declared with @racket[module*] can @racket[require]
its enclosing module, but the enclosing module cannot
@racket[require] the submodule. In addition, a @racket[module*]
form can specify @racket[#f] as its
@racket[_initial-module-path], in which case the submodule sees
all of the enclosing module's bindings---including bindings
that are not exported via @racket[provide].}
]
As an example of @racket[module*], the following variant of
@filepath{cake.rkt} includes a @racket[main] submodule that calls
@racket[print-cake]:
@racketmod[
#:file "cake.rkt"
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* main #f
(print-cake 10))
]
Running a module does not run its @racket[module*]-defined submodules,
since the enclosing module cannot directly reference
@racket[module*]-defined submodules. Nevertheless, running the above
module via @exec{racket} or DrRacket prints a cake with 10 candles,
because the @racket[main] submodule} is a special case.
When a module is provided as a program name to the @exec{racket}
executable or run directly within DrRacket, if the module has a
@as-index{@racket[main] submodule}, the @racket[main] submodule is run after its
enclosing module. Declaring a @racket[main] submodule is often a
useful describe tests or other extra actions to be performed when a
module is run directly instead of @racket[required] as a library
within a larger program.
A @racket[main] submodule does not have to be declared with
@racket[module*]. If the @racket[main] module does not need to use
bindings from its enclosing module, it can be declared with
@racket[module]. A @racket[main] submodule typically uses the
bindings of its enclosing module, however, so @racket[main] is usually
declared with @racket[module*].
Submodules can be nested within submodules, and a submodule can be
referenced directly by a module other than its enclosing module by
using a @racket[submod] path as described in the
@seclink["module-paths"]{next section}.
@; ----------------------------------------------------------------------
@close-eval[cake-eval]

View File

@ -6,6 +6,7 @@
@defmodule[syntax/modcode]
@defproc[(get-module-code [path path?]
[#:submodule-path submodule-path (listof symbol?) '()]
[#:sub-path compiled-subdir0 (and/c path-string? relative-path?) "compiled"]
[compiled-subdir (and/c path-string? relative-path?) compiled-subdir0]
[#:compile compile-proc0 (any/c . -> . any) compile]
@ -24,7 +25,9 @@
any]{
Returns a compiled expression for the declaration of the module
specified by @racket[path].
specified by @racket[path] and @racket[submodule-path], where
@racket[submodule-path] is empty for a root module or a list for a
submodule.
The @racket[compiled-subdir] argument defaults to @racket["compiled"];
it specifies the sub-directory to search for a compiled version of the

View File

@ -334,7 +334,8 @@ reading of the module language.}
@defproc[(make-meta-reader [self-sym symbol?]
[path-desc-str string?]
[#:read-spec read-spec (input-port? . -> . any/c) (lambda (in) ....)]
[module-path-parser (any/c . -> . (or/c module-path? #f))]
[module-path-parser (any/c . -> . (or/c module-path? #f
(vectorof module-path?)))]
[convert-read (procedure? . -> . procedure?)]
[convert-read-syntax (procedure? . -> . procedure?)]
[convert-get-info (procedure? . -> . procedure?)])
@ -367,6 +368,8 @@ description of the expected language form in the error message.
The result of @racket[read-spec] is converted to a module path using
@racket[module-path-parser]. If @racket[module-path-parser] produces
a vector of module paths, they are tried in order using
@racket[module-declared?]. If @racket[module-path-parser] produces
@racket[#f], a reader exception is raised in the same way as when
@racket[read-spec] produces a @racket[#f]. The @racketmodname[planet]
languages supply a @racket[module-path-parser] that converts a byte