MIT Scheme User's Manual: Using Scheme

[ < ] | [ > ] |  | [ << ] | [ Up ] | [ >> ] |  |  |  |  | [Top] | [Contents] | [Index] | [ ? ]

# 3. Using Scheme

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.

> 3.1 The Read-Eval-Print Loop |  |
> 3.2 Loading Files |  |
> 3.3 World Images |  |
> 3.4 Garbage Collection |  |

[ < ] | [ > ] |  | [ << ] | [ Up ] | [ >> ] |  |  |  |  | [Top] | [Contents] | [Index] | [ ? ]

## 3.1 The Read-Eval-Print Loop

When you first start up Scheme from the command line, 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.

> 3.1.1 The Prompt and Level Number |  |
> 3.1.2 Interrupting |  |
> 3.1.3 Restarting |  |
> 3.1.4 The Current REPL Environment |  |

[ < ] | [ > ] |  | [ << ] | [ Up ] | [ >> ] |  |  |  |  | [Top] | [Contents] | [Index] | [ ? ]

### 3.1.1 The Prompt and Level Number

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.

[ < ] | [ > ] |  | [ << ] | [ Up ] | [ >> ] |  |  |  |  | [Top] | [Contents] | [Index] | [ ? ]

### 3.1.2 Interrupting

Scheme has several interrupt keys, which vary depending on the underlying operating system: under unix, `C-g` and `C-c`; under OS/2 and Windows, `C-g`, `C-b`, `C-x` and `C-u`. 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 unix, type `C-c ?` for more possibilities. Note that in any given implementation, only a subset of the following keys is available.

`C-c C-c`
`C-g`
  Abort whatever Scheme evaluation is currently running and return to the top-level REPL. If no evaluation is running, this is equivalent to evaluating

      (cmdl-interrupt/abort-top-level)

`C-c C-x`
`C-x`
  Abort whatever Scheme evaluation is currently running and return to the "current" REPL. If no evaluation is running, this is equivalent to evaluating

      (cmdl-interrupt/abort-nearest)

`C-c C-u`
`C-u`
  Abort whatever Scheme evaluation is running and go up one level. If you are already at level number 1, the evaluation is aborted, leaving you at level 1. If no evaluation is running, this is equivalent to evaluating

      (cmdl-interrupt/abort-previous)

`C-c C-b`
`C-b`
  Suspend whatever Scheme evaluation is running and start a breakpoint REPL. The evaluation can be resumed by evaluating

      (continue)

  in that REPL at any time.

`C-c q`
  Similar to typing `(exit)` at the REPL, except that it works even if Scheme is running an evaluation, and does not request confirmation.

`C-c z`
  Similar to typing `(quit)` at the REPL, except that it works even if Scheme is running an evaluation.

`C-c i`
  Ignore the interrupt. Type this if you made a mistake and didn't really mean to type `C-c`.

`C-c ?`
  Print help information. This will describe any other options not documented here.

[ < ] | [ > ] |  | [ << ] | [ Up ] | [ >> ] |  |  |  |  | [Top] | [Contents] | [Index] | [ ? ]

### 3.1.3 Restarting

Another way to exit a REPL is to use the `restart` procedure:

procedure+: restart [k]
  This procedure selects and invokes a restart method. The list of restart methods is different for each REPL and for each error; in the case of an error REPL, this list is printed when the REPL is started:

      ;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 ]=>

[ < ] | [ > ] |  | [ << ] | [ Up ] | [ >> ] |  |  |  |  | [Top] | [Contents] | [Index] | [ ? ]

### 3.1.4 The Current REPL Environment

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)

Here is the procedure that changes the REPL's environment:

procedure+: ge environment
  Changes the current REPL environment to be 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.

procedure+: pe
  This procedure is useful for finding out which environment you are in (`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.

[ < ] | [ > ] |  | [ << ] | [ Up ] | [ >> ] |  |  |  |  | [Top] | [Contents] | [Index] | [ ? ]

## 3.2 Loading Files

To load files of Scheme code, use the procedure `load`:

procedure: load filename [environment [syntax-table [purify?]]]
  Filename may be a string naming a file, or a list of strings naming multiple files. Environment, if given, is the environment to evaluate the file in; if not given the current REPL environment is used.

  Syntax-table is no longer used and if supplied will be ignored.

  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 3.4 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 section `Components of Pathnames' in MIT Scheme Reference Manual.)

variable+: load-noisily?
  If `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.)

variable+: load/default-types
  When load is given a pathname without a type, it uses the value of this variable to determine what pathname types to look for and how to load the file. `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 section `Working Directory' in MIT Scheme Reference Manual. Files may be loaded when Scheme first starts; see the `-load` command-line option for details.

procedure+: load-option symbol [no-error?]
  Loads the option specified by symbol; if already loaded, does nothing. Returns symbol; if there is no such option, an error is signalled. However, if no-error? is specified and true, no error is signalled in this case, and `#f` is returned.

  A number of built-in options are defined:

  `compress`
    Support to compress and uncompress files. Undocumented; see the source file ``runtime/cpress.scm`'. Used by the runtime system for compression of compiled-code debugging information.

  `format`
    The `format` procedure. See section `Format' in MIT Scheme Reference Manual.

  `gdbm`
    Support to access `gdbm` databases. Undocumented; see the source files ``runtime/gdbm.scm`' and ``microcode/prgdbm.c`'.

  `hash-table`
    The hash-table data type. See section `Hash Tables' in MIT Scheme Reference Manual.

  `ordered-vector`
    Support to search and do completion on vectors of ordered elements. Undocumented; see the source file ``runtime/ordvec.scm`'.

  `rb-tree`
    The red-black tree data type. See section `Red-Black Trees' in MIT Scheme Reference Manual.

  `regular-expression`
    Support to search and match strings for regular expressions. See section `Regular Expressions' in MIT Scheme Reference Manual.

  `stepper`
    Support to step through the evaluation of Scheme expressions. Undocumented; see the source file ``runtime/ystep.scm`'. Used by the Edwin command `step-expression`.

  `subprocess`
    Support to run other programs as subprocesses of the Scheme process. Undocumented; see the source file ``runtime/process.scm`'. Used extensively by Edwin.

  `synchronous-subprocess`
    Support to run synchronous subprocesses. See section `Subprocesses' in MIT Scheme Reference Manual.

  `wt-tree`
    The weight-balanced tree data type. See section `Weight-Balanced Trees' in MIT Scheme Reference Manual.

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)

procedure+: define-load-option symbol thunk ...
  Each thunk must be a procedure of no arguments. Defines the load option named symbol. When the procedure `load-option` is called with symbol as an argument, the thunk arguments are executed in order from left to right.

[ < ] | [ > ] |  | [ << ] | [ Up ] | [ >> ] |  |  |  |  | [Top] | [Contents] | [Index] | [ ? ]

## 3.3 World Images

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 and data 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`.

procedure+: disk-save filename [identify]
  Causes a band to be written to the file specified by filename. The optional argument identify controls what happens when that band is restored, as follows:

  not specified
    Start up in the top-level REPL, identifying the world in the normal way.

  a string
    Do the same thing except print that string instead of ``Scheme`' when restarting.

  the constant `#t`
    Restart exactly where you were when the call to `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.

  the constant `#f`
    Just like `#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.

[ < ] | [ > ] |  | [ << ] | [ Up ] | [ >> ] |  |  |  |  | [Top] | [Contents] | [Index] | [ ? ]

## 3.4 Garbage Collection

This section describes procedures that control garbage collection. See section 2.3 Memory Usage, for a discussion of how MIT Scheme uses memory.

procedure+: gc-flip [safety-margin]
  Forces a garbage collection to occur. Returns the number of words of storage available after collection, an exact non-negative integer.

  Safety-margin determines the number of words of storage available to system tasks after the need for a garbage collection is detected and before the garbage collector is started. (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.

procedure+: purify object [pure-space? [queue?]]
  Moves object from the heap into constant space. Has no effect if object is already stored in constant space. Object is moved in its entirety; if it is a compound object such as a list, a vector, or a record, then all of the objects that object points to are also moved to constant space.

  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?, if `#f`, specifies that object should be moved to constant space immediately; otherwise object is 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.

procedure+: flush-purification-queue!
  Forces any pending queued purification requests to be processed. This examines the `purify` queue, and if it contains any requests, forces a garbage collection to process them. If the queue is empty, does nothing.

procedure+: print-gc-statistics
  Prints out information about memory allocation and the garbage collector. The information is printed to the current output port. Shows how much space is "in use" and how much is "free", separately for the heap and constant space. The amounts are shown in words, and also in 1024-word blocks; the block figures make it convenient to use these numbers to adjust the arguments given to the `-heap` and `-constant` command-line options. Following the allocation figures, information about the most recent 8 garbage collections is shown, in the same format as a GC notification.

  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

procedure+: set-gc-notification! [on?]
  Controls whether the user is notified of garbage collections. If on? is true, notification is enabled; otherwise notification is disabled. If on? is not given, it defaults to `#t`. When Scheme starts, 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 CPU time percentage 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.

procedure+: toggle-gc-notification!
  Toggles GC notification on and off. If GC notification is turned on, turns it off; otherwise turns it on.

[ << ] | [ >> ] |  |  |  |  |  | [Top] | [Contents] | [Index] | [ ? ]

This document was generated by Chris Hanson on June, 17 2002 using texi2html