Jscheme
(Scheme (in Java (by Peter Norvig)))

Jscheme is:

  • Lisp: An interpreter for the Scheme dialect.
  • Java: Written in Pure Java 1.1.
  • Complete: meets the R4RS standard, except for three limitations.
  • Compact: About 50KB source, 30KB classes.jar.
  • Integrated: You can call any Java method.
  • Open: Generous free license agreement.

Learn More:

Jscheme is my implementation of Scheme in Java. This page presents Jscheme version 1.4, the last version that I released (in April 1998). If you want a mercilessly small, easily modifiable version, this is it. Since April 1998, development has been picked up by others, notably Tim Hickey at Brandeis and Ken Anderson at BBN. If you want the latest, full-featured version, look at:

Jscheme at Sourceforge.net   sourceforge logo

Jscheme 1.4 Extensions

There are a few things that are in Jscheme 1.4 that are not in R4RS Scheme:

java jscheme.Scheme files Any arguments on the command line are interpreted as files to be loaded.  For example, you can test the system for compliance with the Scheme standard with:
java jscheme.Scheme r4rstest.scm
(first list)
(second list)
(third list)
(rest list)
These are the same as in Common Lisp.
(macro (args) body)This syntax is defined so that (define name (macro (args) body)) is just like Common Lisp's (defmacro name (args) body). I realize I should add a mode where this syntax is not used.
(error x...)Prints an error mentioning all the arguments, and then throws out to the read-eval-print loop.
(time-call proc k)
(time-call proc)
calls the procedure proc and returns a three-element list of the result, the number of milliseconds and the number of bytes consumed by the call. If k is given, it calls k times, and returns the result from the last call.
(time exp k)
(time exp)
This macro evaluates exp k times (or once if k is not given). It then returns the same statistics as time-call. Example:
> (time (zero? 0) 1000)
(#t (53 msec) (48000 bytes))
(exit k)
(exit)
exits from Java, returning k as the exit code if it is present and is a number, otherwise the exit code is 0.
(class string)returns the Java class named by the string.  For example, (class "java.awt.Frame").
(new class)creates a new instance of the Java class.  For example, (new (class "java.awt.Frame"))
(method m o cs...)returns a procedure that invokes a Java method m on an object o. The cs are names of classes (or class objects) for the arguments of the method. For example:
(define show (method "show" "java.awt.Frame"))
(show (new "java.awt.Frame"))

Limitations

Jscheme implements all of R4RS except that:

  1. Continuations can only be used as escape procedures; that is they can only be called while the surrounding try/catch is still in scope.
  2. read does not handle all the lexical syntax for numbers (e.g. #e123#.#F-3+#b1/#d4#i). The language standard says "any particular implementation may support only some" of the written notations for numbers, so this does not appear to be a violation.
  3. The distinction between exact and inexact is not right. I represent all numbers as double precision floating point, and define both exact? and integer? as
    (lambda (x)
      (and (number? x)
           (= x (round x))
           (< (- x 1) x (+ x 1))))
    

To Do

There are a few things on my "to do" list:

  1. Better support for errors: catch some errors that kill the system, allow user to interrupt and get into a break loop or back to top level, provide for recovery from errors.
  2. Better integration with Java methods.
  3. Better way to use multi-threading.
  4. Functions for web access.
  5. A GUI.
  6. An applet version available over the web.
  7. Add BigInteger or BigDecimal numbers. Or maybe a new LongRational class.
  8. Make everything 10 to 50 times faster (I hope) by pre-treating expressions before evaluating.
  9. R5RS support. This requires hygienic macros (which Dorai already did for me) and fifteen new procedures: two-argument eval, scheme-report-environment, null-environment, interaction-environment, numerator, denominator, rationalize, string-copy, string-fill!, vector-fill!, port?, char-ready?, values, call-with-values, and dynamic-wind. For dynamic-wind, I will probably have the same limitations as with call/cc. I believe it is legal to do
    (define values list)
    (define (call-with-values producer consumer) (apply consumer (producer)))
    

References

Scheme Standards

Scheme Compilation Books

Scheme Implementations (In Java)

General Scheme Resources

Version History

The table below gives code size measurements in bytes and lines, for object and source code. "KB" means 1000 bytes, not 1024. "Source" includes some Scheme code as well as the Java code.

Version
Number
*.class
KB
classes
.jar KB
Source
KB
Source
lines
Major Changes
1.455KB29KB69KB1905No separate scheme file
1.347KB28KB68KB1888less scheme code
1.242KB26KB64KB1803Better javadoc; no PrintStream
1.141KB23KB60KB1745Complete set of R4RS functions
1.040KB22KB57KB1664Passed the test suite.

Dorai Sitaram (ds26@gte.com) kindly contributed a R5RS compliant macro-by-example implementation that works in Jscheme.

Version 1.4: Released April 16, 1998

Version 1.3: Released April 15, 1998

Version 1.2: Released April 10, 1998

Version 1.1: Released March 30, 1998.

Version 1.0: Released March 27, 1998.



Peter Norvig