Go to the first, previous, next, last section, table of contents.
This chapter describes how to use Scheme to evaluate expressions and load programs. It also describes how to save custom "world images", and how to control the garbage collector. Subsequent chapters will describe how to use the compiler, and how to debug your programs.
When you first start up Scheme from the command line (i.e. not under Edwin), you will be typing at a program called the Read-Eval-Print Loop (abbreviated REPL). It displays a prompt at the left hand side of the screen whenever it is waiting for input. You then type an expression (terminating it with RET). Scheme evaluates the expression, prints the result, and gives you another prompt.
The REPL prompt normally has the form
1 ]=>
The `1' in the prompt is a level number, which is always a positive integer. This number is incremented under certain circumstances, the most common being an error. For example, here is what you will see if you type f o o RET after starting Scheme:
;Unbound variable: foo ;To continue, call RESTART with an option number: ; (RESTART 3) => Specify a value to use instead of foo. ; (RESTART 2) => Define foo to a given value. ; (RESTART 1) => Return to read-eval-print level 1. 2 error>
In this case, the level number has been incremented to `2', which
indicates that a new REPL has been started (also the prompt string
has been changed to remind you that the REPL was started because of
an error). The `2' means that this new REPL is "over" the
old one. The original REPL still exists, and is waiting for you to
return to it, for example, by entering (restart 1)
. Furthermore,
if an error occurs while you are in this REPL, yet another
REPL will be started, and the level number will be increased to
`3'. This can continue ad infinitum, but normally it is rare to
use more than a few levels.
The normal way to get out of an error REPL and back to the top level REPL is to use the C-g interrupt. This is a single-keystroke command executed by holding down the CTRL key and pressing the G key. C-g always terminates whatever is running and returns you to the top level REPL immediately.
Note: The appearance of the `error>' prompt does not mean that Scheme is in some weird inconsistent state that you should avoid. It is merely a reminder that your program was in error: an illegal operation was attempted, but it was detected and avoided. Often the best way to find out what is in error is to do some poking around in the error REPL. If you abort out of it, the context of the error will be destroyed, and you may not be able to find out what happened.
Scheme has several interrupt keys, which vary depending on the underlying operating system: under Unix, C-g and C-c; under Windows, C-b, C-x, C-u, C-g and C-c; under OS/2, C-b, C-x, C-u and C-g. The C-g key stops any Scheme evaluation that is running and returns you to the top level REPL. C-c prompts you for another character and performs some action based on that character. It is not necessary to type RET after C-g or C-c, nor is it needed after the character that C-c will ask you for.
Here are the definitions of the more common interrupt keys; on systems that support C-c, type C-c ? for more possibilities. Note that in any given implementation, only a subset of the following keys is available.
(cmdl-interrupt/abort-top-level)
(cmdl-interrupt/abort-nearest)
(cmdl-interrupt/abort-previous)
(continue)in that REPL at any time.
(exit)
at the REPL, except that it works
even if Scheme is running an evaluation, and does not request
confirmation.
(quit)
at the REPL, except that it works
even if Scheme is running an evaluation.
Another way to exit a REPL is to use the restart
procedure:
;Unbound variable: foo ;To continue, call RESTART with an option number: ; (RESTART 3) => Specify a value to use instead of foo. ; (RESTART 2) => Define foo to a given value. ; (RESTART 1) => Return to read-eval-print level 1. 2 error>
If the k argument is given, it must be a positive integer index
into the list (in the example it must be between one and three
inclusive). The integer k selects an item from the list and
invokes it. If k is not given, restart
prints the list and
prompts for the integer index:
2 error> (restart) ;Choose an option by number: ; 3: Specify a value to use instead of foo. ; 2: Define foo to a given value. ; 1: Return to read-eval-print level 1. Option number:
The simplest restart methods just perform their actions. For example:
2 error> (restart 1) ;Abort! 1 ]=>
Other methods will prompt for more input before continuing:
2 error> (restart) ;Choose an option by number: ; 3: Specify a value to use instead of foo. ; 2: Define foo to a given value. ; 1: Return to read-eval-print level 1. Option number: 3 Value to use instead of foo: '(a b) ;Value: (a b) 1 ]=>
Every REPL has a current environment, which is the place
where expressions are evaluated and definitions are stored. When Scheme
is started, this environment is the value of the variable
user-initial-environment
. There are a number of other
environments in the system, for example
system-global-environment
, where the runtime system's bindings
are stored.
You can get the current REPL environment by evaluating
(nearest-repl/environment)
There are several other ways to obtain environments. For example, if you have a procedure object, you can get a pointer to the environment in which it was closed by evaluating
(procedure-environment procedure)
Your programs create new environments whenever a procedure is called.
Here is the procedure that changes the REPL's environment:
ge
stands for "Goto Environment"). Environment is
allowed to be a procedure as well as an environment object. If it is a
procedure, then the closing environment of that procedure is used in its
place.
pe
stands for "Print Environment"). If the current REPL
environment belongs to a package, then pe
returns the package
name (a list of symbols). If the current REPL environment does not
belong to a package then the environment is returned.
if
, lambda
). If you write macros, you may want to
make your own syntax table, in which case it is useful to be able to
make that syntax table be the current one; gst
allows you to do
that.
To load files of Scheme code, use the procedure load
:
The optional argument purify? is a boolean that says whether to
move the contents of the file into constant space after it is loaded but
before it is evaluated. This is performed by calling the procedure
purify
(see section Garbage Collection). If purify? is given
and true, this is done; otherwise it is not.
load
determines whether the file to be loaded is binary or source
code, and performs the appropriate action. By convention, files of
source code have a pathname type of "scm"
, and files of binary
SCode have pathname type "bin"
. Native-code binaries have
pathname type "com"
. (See the description of
pathname-type
in the reference manual.)
load-noisily?
is set to #t
, load
will print the
value of each expression in the file as it is evaluated. Otherwise,
nothing is printed except for the value of the last expression in the
file. (Note: the noisy loading feature is implemented for source-code
files only.)
load/default-types
is a list of associations that maps
pathname types (strings) to loader procedures. load
tries the
pathname types in the order that they appear in the list. The initial
value of this variable has pathname types in this order:
"com" "so" "sl" "bin" "scm"
This means that, for example, (load "foo")
will try to load
`foo.com' first, and `foo.scm' only after looking for and
failing to find the other pathname types.
All pathnames are interpreted relative to a working directory, which is
initialized when Scheme is started. The working directory can be
obtained by calling the procedure pwd
or modified by calling the
procedure cd
; see the reference manual for details. Files may be
loaded when Scheme first starts; see the `-load' command-line
option for details.
#f
is returned.
A number of built-in options are defined:
compress
format
format
procedure. Documented in the Reference Manual.
hash-table
ordered-vector
rb-tree
stepper
subprocess
wt-tree
In addition to the built-in options, you may define other options to be
loaded by load-options
by modifying the file `optiondb.scm'
on the library path. An example file is included with the distribution;
normally this file consists of a series of calls to the procedure
define-load-option
, terminated by the expression
(further-load-options standard-load-options)
load-option
is
called with symbol as an argument, the thunk arguments are
executed in order from left to right.
A world image, also called a band, is a file that contains a
complete Scheme system, perhaps additionally including user application
code. Scheme provides a method for saving and restoring world images.
The method writes a file containing all of the Scheme code in the
running process. The file `runtime.com' that is loaded by the
microcode is just such a band. To make your own band, use the procedure
disk-save
.
#t
disk-save
was
performed. This is especially useful for saving your state when an
error has occurred and you are not in the top-level REPL.
#f
#t
, except that the runtime system will not perform
normal restart initializations; in particular, it will not load your
init file.
To restore a saved band, give the `-band' option when starting
Scheme. Alternatively, evaluate (disk-restore filename)
,
which will destroy the current world, replacing it with the saved world.
The argument to disk-restore
may be omitted, in which case it
defaults to the filename from which the current world was last restored.
Note: with the C back end, disk-save
is not very useful. The
reason is that compiled procedures are compiled C code that has been
dynamically linked in, and disk-save
does not save any C
procedures. Your system is a C back end system if the following
expression does not evaluate to #f
:
(system-library-directory-pathname "shared")
Note: when restoring a saved band, the Scheme executable must be
configured with a large enough constant space and heap to hold the
band's contents. If you attempt to restore a band using the
`-band' option, and the band is too large, Scheme will write an
error message that tells you the appropriate command-line options needed
to load that band. If you attempt restore a too-large band using
disk-restore
, Scheme will signal an error, but will not provide
the configuration information. In general, the configuration that was
used to save a band is sufficiently large to restore it.
This section describes procedures that control garbage collection. See section Memory Usage, for a discussion of how MIT Scheme uses memory.
Safety-margin determines the number of words of storage available for system tasks in-between detecting the need for a garbage collection and entering the garbage collector proper. (An example of such a system task is changing the run-light to show "gc" when scheme is running under Emacs.) Note well: you should not specify safety-margin unless you know what you are doing. If you specify a value that is too small, you can put Scheme in an unusable state.
There are three important effects associated with moving an object to constant space. The first and most important effect is that the object takes up half as much space, because when in the heap, the system must reserve space for the object in both the active heap and the inactive heap; if the object is in constant space it is not copied and therefore no extra space is required. The second effect is that garbage collection will take less time, because object will no longer be copied. The third effect is that the space allocated to object is permanently allocated, because constant space is never cleaned; any unreachable objects in constant space remain there until the Scheme process is terminated.
The optional argument pure-space? is obsolete; it defaults to
#t
and when explicitly specified should always be #t
.
The optional argument queue? specifies whether object should
be moved to constant space immediately, or should be queued to be moved
during the next garbage collection. This argument defaults to
#t
. The reason for queuing these requests is that moving an
object to constant space requires a garbage collection to occur, a
relatively slow process. By queuing the requests, this overhead is
avoided, because moving an object during a garbage collection has no
effect on the time of the garbage collection. Furthermore, if several
requests are queued, they can all be processed together in one garbage
collection, while if done separately they would each require their own
garbage collection.
purify
queue, and if it contains any requests,
forces a garbage collection to process them. If the queue is empty,
does nothing.
Note that these numbers are accurate at the time that
print-gc-statistics
is called. In the case of the heap, the "in
use" figure shows how much memory has been used since the last garbage
collection, and includes all live objects as well as any uncollected
garbage that has accumulated since then. The only accurate way to
determine the size of live storage is to subtract the value of
`(gc-flip)' from the size of the heap. The size of the heap can be
determined by adding the "in use" and "free" figures reported by
print-gc-statistics
.
(print-gc-statistics) constant in use: 534121 words = 521 blocks + 617 words constant free: 128 words = 0 blocks + 128 words heap in use: 34845 words = 34 blocks + 29 words heap free: 205530 words = 200 blocks + 730 words GC #1: took: 0.13 (81%) CPU time, 0.15 (1%) real time; free: 207210 ;No value
#f
, notification is enabled; otherwise
notification is disabled. By default, notification is disabled.
The notification appears as a single line like the following, showing how many garbage collections have occurred, the time taken to perform the garbage collection and the free storage remaining (in words) after collection.
GC #5: took: 0.50 (8%) CPU time, 0.70 (2%) real time; free: 364346
To operate comfortably, the amount of free storage after garbage collection should be a substantial proportion of the heap size. If the percentage CPU time is consistently high (over 20%), you should consider running with a larger heap. A rough rule of thumb to halve the GC overhead is to take the amount of free storage, divide by 1000, and add this figure to the current value used for the `-heap' command-line option. Unfortunately there is no way to adjust the heap size without restarting Scheme.
Go to the first, previous, next, last section, table of contents.