scheme/load in guide
svn: r12466
This commit is contained in:
parent
dfd62c1e92
commit
b07b874e2e
|
@ -92,6 +92,12 @@ downloadable packages contributed by PLT Scheme users.
|
|||
#:date "2004"
|
||||
#:url "http://www.cs.utah.edu/plt/publications/oopsla04-gff.pdf")
|
||||
|
||||
(bib-entry #:key "Flatt02"
|
||||
#:author "Matthew Flatt"
|
||||
#:title "Composable and Compilable Macros: You Want it When?"
|
||||
#:location "International Conference on Functional Programming"
|
||||
#:date "2002")
|
||||
|
||||
(bib-entry #:key "Flatt06"
|
||||
#:author "Matthew Flatt, Robert Bruce Findler, and Matthias Felleisen"
|
||||
#:title "Scheme with Classes, Mixins, and Traits (invited tutorial)"
|
||||
|
|
|
@ -5,12 +5,9 @@
|
|||
|
||||
@title[#:tag "modules" #:style 'toc]{Modules}
|
||||
|
||||
Scheme definitions and expressions are normally written inside of a
|
||||
module. Although a @tech{REPL} evaluates definitions and expressions outside
|
||||
of a module for exploration and debugging purposes, and although
|
||||
@scheme[load] can evaluate definitions and expressions from a file as
|
||||
if they appeared in a @tech{REPL} interaction, code that is meant to last for
|
||||
more than a few seconds belongs in a module.
|
||||
|
||||
Modules let you organize Scheme code into multiple files and reusable
|
||||
libraries.
|
||||
|
||||
@local-table-of-contents[]
|
||||
|
||||
|
|
|
@ -385,3 +385,135 @@ example, since the enclosing module requires
|
|||
instance of @schememodname[scheme/class]. Moreover, that instance is
|
||||
the same as the one imported into the module, so the class datatype is
|
||||
shared.
|
||||
|
||||
@; ----------------------------------------------------------------------
|
||||
|
||||
@section[#:tag "load"]{Scripting Evaluation and Using @scheme[load]}
|
||||
|
||||
Historically, Scheme and Lisp systems did not offer module
|
||||
systems. Instead, large programs were built by essentially scripting
|
||||
the @tech{REPL} to evaluate program fragments in a particular order.
|
||||
While @tech{REPL} scripting turns out to be a bad way to structure
|
||||
programs and libraries, it is still sometimes a useful capability.
|
||||
|
||||
@margin-note{Describing a program via @scheme[load] interacts
|
||||
especially badly with macro-defined language extensions
|
||||
@cite["Flatt02"].}
|
||||
|
||||
The @scheme[load] function runs a @tech{REPL} script by
|
||||
@scheme[read]ing S-expressions from a file, one by one, and passing
|
||||
them to @scheme[eval]. If a file @filepath{place.scm} contains
|
||||
|
||||
@schemeblock[
|
||||
(define city "Salt Lake City")
|
||||
(define state "Utah")
|
||||
(printf "~a, ~a\n" city state)
|
||||
]
|
||||
|
||||
then it can be loaded in a @tech{REPL}:
|
||||
|
||||
@interaction[
|
||||
(eval:alts (load "place.scm") (begin (define city "Salt Lake City")
|
||||
(printf "~a, Utah\n" city)))
|
||||
city
|
||||
]
|
||||
|
||||
Since @scheme[load] uses @scheme[eval], however, a module like the
|
||||
following generally will not work---for the same reasons described in
|
||||
@secref["namespaces"]:
|
||||
|
||||
@schememod[
|
||||
scheme
|
||||
|
||||
(define there "Utopia")
|
||||
|
||||
(load "here.scm")
|
||||
]
|
||||
|
||||
The current namespace for evaluating the content of
|
||||
@filepath{here.scm} is likely to be empty; in any case, you cannot get
|
||||
@scheme[there] from @filepath{here.scm}. Also, any definitions in
|
||||
@filepath{here.scm} will not become visible for use within the module;
|
||||
after all, the @scheme[load] happens dynamically, while references to
|
||||
identifiers within the module are resolved lexically, and therefore
|
||||
statically.
|
||||
|
||||
Unlike @scheme[eval], @scheme[load] does not accept a namespace
|
||||
argument. To supply a namespace to @scheme[load], set the
|
||||
@scheme[current-namespace] parameter. The following example evaluates
|
||||
the expressions in @filepath{here.scm} using the bindings of the
|
||||
@schememodname[scheme/base] module:
|
||||
|
||||
@schememod[
|
||||
scheme
|
||||
|
||||
(parameterize ([current-namespace (make-base-namespace)])
|
||||
(load "here.scm"))
|
||||
]
|
||||
|
||||
You can even use @scheme[namespace-anchor->namespace] to make the
|
||||
bindings of the enclosing module accessible for dynamic evaluation. In
|
||||
the following example, when @filepath{here.scm} is @scheme[load]ed, it
|
||||
can refer to @scheme[there] as well as the bindings of
|
||||
@schememodname[scheme]:
|
||||
|
||||
@schememod[
|
||||
scheme
|
||||
|
||||
(define there "Utopia")
|
||||
|
||||
(define-namespace-anchor a)
|
||||
(parameterize ([current-namespace (namespace-anchor->namespace a)])
|
||||
(load "here.scm"))
|
||||
]
|
||||
|
||||
Still, if @filepath{here.scm} defines any identifiers, the definitions
|
||||
cannot be directly (i.e., statically) referenced by in the enclosing
|
||||
module.
|
||||
|
||||
The @schememodname[scheme/load] module language is different from
|
||||
@schememodname[scheme] or @schememodname[scheme/base]. A module using
|
||||
@schememodname[scheme/load] treats all of its content as dynamic,
|
||||
passing each form in the module body to @scheme[eval] (using a
|
||||
namespace that is initialized with @schememodname[scheme]). As a
|
||||
result, uses of @scheme[eval] and @scheme[load] in the module body see
|
||||
the same dynamic namespace as immediate body forms. For example, if
|
||||
@filepath{here.scm} contains
|
||||
|
||||
@schemeblock[
|
||||
(define here "Morporkia")
|
||||
(define (go!) (set! here there))
|
||||
]
|
||||
|
||||
then running
|
||||
|
||||
@schememod[
|
||||
scheme/load
|
||||
|
||||
(define there "Utopia")
|
||||
|
||||
(load "here.scm")
|
||||
|
||||
(go!)
|
||||
(printf "~a\n" here)
|
||||
]
|
||||
|
||||
prints ``Utopia''.
|
||||
|
||||
Drawbacks of using @schememodname[scheme/load] include reduced
|
||||
error checking, tool support, and performance. For example, with the
|
||||
program
|
||||
|
||||
@schememod[
|
||||
scheme/load
|
||||
|
||||
(define good 5)
|
||||
(printf "running\n")
|
||||
good
|
||||
bad
|
||||
]
|
||||
|
||||
DrScheme's @onscreen{Check Syntax} tool cannot tell that the second
|
||||
@scheme[good] is a reference to the first, and the unbound reference
|
||||
to @scheme[bad] is reported only at run time instead of rejected
|
||||
syntactically.
|
||||
|
|
|
@ -198,11 +198,11 @@ tempted to put just
|
|||
(substring str 0 5))
|
||||
]
|
||||
|
||||
into @filepath{piece.ss} and run @exec{mzscheme} with
|
||||
into @filepath{piece.scm} and run @exec{mzscheme} with
|
||||
|
||||
@interaction[
|
||||
#:eval piece-eval
|
||||
(eval:alts (load "piece.ss") (void))
|
||||
(eval:alts (load "piece.scm") (void))
|
||||
(piece "howdy universe")
|
||||
]
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user