[plt-scheme] Interactive stuff for console use

From: Eli Barzilay (eli at barzilay.org)
Date: Sun Oct 15 16:18:28 EDT 2006

I have gathered a few hacks that make it easier to use mzscheme/mred
on a console (or through Emacs etc).  Some of these things are useful
in DrScheme too, but it's mostly intended for interactive console use.
(Note: it is *not* intended to replace DrScheme in any way.)  I've put
this at


Currently, it's a single file -- you can use it directly as your
.mzschemerc, or make your .mzschemerc load it (yes: `load', it has a
bunch of mosules and expressions).  If enough people find it useful, I
will probably make it into a more proper collection and perhaps
distribute it on planet.

The list of features are listed at the top of the file.  But to make
it easy to see what you can get from it:

* Defines a `debug' module that provides a few useful utilities for
  use in code while debugging:
  > (eprintf fmt arg ...)
    Like `printf', but uses the current error port.
  > (warn ...)
    Same as `error', but only prints the error message.
  > ***
  > (*** value)
  > (*** fmt-string args ...)
    This is macro that is useful for debugging: the first form prints
    (on stderr) the source file and line number, the second also
    prints a value (and returns it), and the third uses a format
    string.  For example, to see where a problem happens in a
    function, you spread `***'s around, and the printout.
  > (define*** (name args ...) ...)
    Macro that defines `name' as a traced function.  (The idea is that
    you append a `***' to functions that you want to trace.)  This is
    a cheap hack: it kills tail-recursiveness.
  The `***' is supposed to be a token that stands out textually in
  *your* code while you're debugging it, so it is customizable: set
  the `MZ_DEBUGGER_TOKEN' environment variable to whatever you want --
  for example, set it to `@@' and you'll get bindings for `@@' and
  `define@@' instead of the above.

* Provides a `mzscheme*' module that can be used as a `mzscheme'
  drop-in replacement.  Basically lets you be lazy and change
  `mzscheme' to `mzscheme*' instead of adding a `(require debug)'.

* The following REPL functionality is used only when there is some REPL
  interaction, so non-interactive use (scripts) is not affected.

* Uses the readline library if we're running in an xterm (and if it's present).
  (Again, triggered by repl interaction.)

* Makes a convenient syntax for requiring, hooked on using 'foo as a module
    (require 'foo1/foo2/bar) will require the first of
      (lib "bar" "foo1" "foo2")
      (lib "bar.ss" "foo1" "foo2")
      (lib "bar.scm" "foo1" "foo2")
      (lib "bar{,.ss,.scm}" "mzlib" "foo1" "foo2")
      (lib "bar{.ss,.scm}" "foo1" "foo2" "bar") when `bar' is suffixless
  Here are a few examples for `obvious' things that it gets right:
    (require 'list)         -> (lib "list.ss")
    (require 'net/sendmail) -> (lib "sendmail.ss" "net")
    (require 'r5rs)         -> (lib "r5rs.ss" "r5rs")
    (require 'foo)          -> (file "foo.ss") ; if the file exists
  This is intended for convenient interactive use, not for programs.

* Toplevel commands, in the form of ",cmd".  Some of these commands
  read an argument that is at the end of the line (eg, ",cd foo",
  ",ls"), and some read an expression (eg, ",stx (...expr...)").
  These commands make it convenient to perform many otherwise-tedious
  operations in MzScheme.  Use ",h" for a list of available commands.

* Two of these commads allow you to go into and out of module namespaces.  The
  prompt shows you which module you're currently in.  For example:
    > ,enter 'list
    (quote list)> foldl
    (quote list)> ,toplevel
  To enable more debugging capabilities, uncomment the
    (compile-enforce-module-constants #f)
  line, which will avoid compiler inlining (and enable arbitrary
  mutation).  (Better than putting it in your .mzschemerc, because it
  will have an effect only on REPL use.)

* Previous toplevel results are accessible: `^' is the last result,
  `^^' is the second to last (or the second value of the last
  multiple-value result) etc.  This is done in a way that is trying to
  avoid clobbering a binding that you already have for these

          ((lambda (x) (x x)) (lambda (x) (x x)))          Eli Barzilay:
                  http://www.barzilay.org/                 Maze is Life!

Posted on the users mailing list.