123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161 |
- @node Using the module system
- @section Using the module system
- Scheme48 is deeply integrated with an advanced module system. For
- complete detail of its module system, @pxref{Module system}. Briefly,
- however:
- @itemize
- @item @dfn{Packages} are top-level environments suitable for
- evaluating expressions and definitions, either interactively, from
- files loaded on-the-fly, or as the bodies of modules. They can also
- access bindings exported by structures by @dfn{opening} the
- structures.
- @item @dfn{Structures} are libraries, or implementations of
- interfaces, exporting sets of bindings that packages can access.
- Underlying structures are usually packages, in which the user can, in
- some cases, interactively evaluate code during development.
- @end itemize
- Scheme48's usual development system, the command processor, provides a
- number of commands for working with the module system. For complete
- details, @pxref{Module commands}. Chief among these commands are
- @command{,open} and @command{,in}. @samp{,open @var{struct} @dots{}}
- makes all of the bindings from each of @var{struct} @dots{} available
- in the interaction environment. Many of the sections in this manual
- describe one or more structures with the name they are given. For
- example, in order to use, or open, the multi-dimensional array library
- in the current interaction environment, one would enter
- @lisp
- ,open arrays@end lisp
- @noindent
- to the command processor. @samp{,in @var{struct}} sets the
- interaction environment to be the package underlying @var{struct}.
- For instance, if, during development, the user decides that the
- package of the existing structure @code{foo} should open the structure
- @code{bar}, he might type
- @lisp
- ,in foo
- ,open bar@end lisp
- The initial interaction environment is known as the @dfn{user
- package}; the interaction environment may be reverted to the user
- package with the @command{,user} command.
- Module descriptions, or code in the @embedref{Module configuration
- language, module configuration language} should be loaded into the
- special environment for that language with the @code{,config} command
- (@pxref{Module commands}). @Eg{}, if @file{packages.scm} contains a
- set of module descriptions that the user wishes to load, among which
- is the definition of a structure @code{frobozz} which he wishes to
- open, he will typically send the following to the command processor
- prompt:
- @lisp
- ,config ,load packages.scm
- ,open frobozz@end lisp
- @strong{Note:} These are commands for the interactive command
- processor, @emph{not} special directives to store in files to work
- with the module system. The module language is disjoint from Scheme;
- for complete detail on it, @pxref{Module system}.
- @subsection Configuration mutation
- @i{(This section was derived from work copyrighted @copyright{}
- 1993--2005 by Richard Kelsey, Jonathan Rees, and Mike Sperber.)}
- @cindex code reloading
- @cindex reloading code
- @texonlyindent
- During program development, it is often desirable to make changes to
- packages and interfaces. In static languages, it is usually necessary
- to re-compile and re-link a program in order for such changes to be
- reflected in a running system. Even in interactive Common Lisp
- systems, a change to a package's exports often requires reloading
- clients that have already mentioned names whose bindings change. In
- those systems, once @code{read} resolves a use of a name to a symbol,
- that resolution is fixed, so a change in the way that a name resolves
- to a symbol can be reflected only by re-@code{read}ing all such
- references.
- The Scheme48 development environment supports rapid turnaround in
- modular program development by allowing mutations to a program's
- configuration and giving a clear semantics to such mutation. The rule
- is that variable bindings in a running program are always resolved
- according to the current structure and interface bindings, even when
- these bindings change as a result of edits to the configuration. For
- example, consider the following:
- @lisp
- (define-interface foo-interface (export a c))
- (define-structure foo foo-interface
- (open scheme)
- (begin (define a 1)
- (define (b x) (+ a x))
- (define (c y) (* (b a) y))))
- (define-structure bar (export d)
- (open scheme foo)
- (begin (define (d w) (+ (b w) a))))@end lisp
- This program has a bug. The variable named @code{b}, which is free in
- the definition of @code{d}, has no binding in @code{bar}'s package.
- Suppose that @code{b} was intended to be exported by @code{foo}, but
- was mistakenly omitted. It is not necessary to re-process @code{bar} or
- any of @code{foo}'s other clients at this point. One need only change
- @code{foo-interface} and inform the development system of that change
- (using, say, an appropriate Emacs command), and @code{foo}'s binding of
- @code{b} will be found when the procedure @code{d} is called and its
- reference to @code{b} actually evaluated.
- Similarly, it is possible to replace a structure; clients of the old
- structure will be modified so that they see bindings from the new one.
- Shadowing is also supported in the same way. Suppose that a client
- package @var{C} opens a structure @code{mumble} that exports a name
- @code{x}, and @code{mumble}'s implementation obtains the binding of
- @code{x} from some other structure @code{frotz}. @var{C} will see the
- binding from @code{frotz}. If one then alters @code{mumble} so that it
- shadows @code{bar}'s binding of @code{x} with a definition of its own,
- procedures in @var{C} that refer to @code{x} will subsequently
- automatically see @code{mumble}'s definition instead of the one from
- @code{frotz} that they saw earlier.
- This semantics might appear to require a large amount of computation on
- every variable reference: the specified behaviour appears to require
- scanning the package's list of opened structures and examining their
- interfaces --- on every variable reference evaluated, not just at
- compile-time. However, the development environment uses caching with
- cache invalidation to make variable references fast, and most of the
- code is invoked only when the virtual machine traps due to a reference
- to an undefined variable.
- @subsection Listing interfaces
- @cindex interfaces
- @stindex list-interfaces
- The @code{list-interfaces} structure provides a utility for examining
- interfaces. It is usually opened into the config package with
- @code{,config ,open list-interfaces} in order to have access to the
- structures & interfaces easily.
- @deffn procedure list-interface struct-or-interface @returns{} unspecified
- Lists all of the bindings exported by @var{struct-or-interface} along
- with their @embedref{Static type system, static types}. For example,
- @lisp
- > ,config ,open list-interfaces
- > ,config (list-interface condvars)
- condvar-has-value? (proc (:condvar) :value)
- condvar-value (proc (:condvar) :value)
- condvar? (proc (:value) :boolean)
- make-condvar (proc (&rest :value) :condvar)
- maybe-commit-and-set-condvar! (proc (:condvar :value) :boolean)
- maybe-commit-and-wait-for-condvar (proc (:condvar) :boolean)
- set-condvar-has-value?! (proc (:condvar :value) :unspecific)
- set-condvar-value! (proc (:condvar :value) :unspecific)@end lisp
- @end deffn
|