Jscheme

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



Jscheme is: Lisp : An interpreter for the Scheme dialect.

: An interpreter for the Scheme dialect. Java : Written in Pure Java 1.1.

: Written in Pure Java 1.1. Complete : meets the R 4 RS standard, except for three limitations.

: meets the R RS standard, except for three limitations. Compact : About 50KB source, 30KB classes.jar.

: About 50KB source, 30KB classes.jar. Integrated : You can call any Java method.

: You can call any Java method. Open: Generous free license agreement. Learn More: Browse the Javadoc documentation.

Browse the source code directory.

See the Design document.

document. Download the source code as jscheme.jar.

Download the object code as classes.jar and do

java jscheme.Scheme scheme-files...

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 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"))

Jscheme implements all of R4RS except that:

Continuations can only be used as escape procedures; that is they can only be called while the surrounding try/catch is still in scope. 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. 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:

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. Better integration with Java methods. Better way to use multi-threading. Functions for web access. A GUI. An applet version available over the web. Add BigInteger or BigDecimal numbers. Or maybe a new LongRational class. Make everything 10 to 50 times faster (I hope) by pre-treating expressions before evaluating. 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

The Revised 4 Report on the Algorithmic Language Scheme (postscript or HTML). The version of the standard that Jscheme is currently based on. See also the r4rstest.scm compliance test.

(postscript or HTML). The version of the standard that Jscheme is currently based on. See also the r4rstest.scm compliance test. The Revised 5 Report on the Algorithmic Language Scheme (postscript or HTML). The very latest version of the standard, also compatible with the IEEE standard.

(postscript or HTML). The very latest version of the standard, also compatible with the IEEE standard. IEEE Standard 1178-1990. IEEE Standard for the Scheme Programming Language (Not available online. You have to buy it from IEEE.)

Scheme Compilation Books

Christian Quenniac's Lisp in Small Pieces is a good reference for interpreting and compiling Lisp.

is a good reference for interpreting and compiling Lisp. Peter Norvig's Paradigms of AI Programming also covers Scheme interpreters and compilers.

also covers Scheme interpreters and compilers. Sussman and Abelson's Structure and Interpretation of Computer Programs is the best book ever written on Computer Science, in my opinion. It also covers Scheme interpreters and compilers.

is the best book ever written on Computer Science, in my opinion. It also covers Scheme interpreters and compilers. Friedman, Wand and Haynes's Essentials of Programming Languages is a good introduction to programming language design and implementation. It also uses Scheme.

Scheme Implementations (In Java)

Michael Travers' Skij (Scheme in Java) is similar enough to Jscheme that if Skij had existed, I wouldn't have done Jscheme. Some minor differences: Skij strings are immutable, in violation of R n Scheme, but in alignment with Java; more of Skij is written in Scheme.

Scheme, but in alignment with Java; more of Skij is written in Scheme. Per Bothner's Kawa is a near-complete R 5 RS Scheme in Java, with many Common-Lisp-like extensions, that compiles to Java byte codes. The resulting code is much faster than Jscheme, but Kawa is 605KB (23K lines) of source code, and 540KB of object code (loaded on demand); more than 10 times more than Jscheme on both counts.

RS Scheme in Java, with many Common-Lisp-like extensions, that compiles to Java byte codes. The resulting code is much faster than Jscheme, but Kawa is 605KB (23K lines) of source code, and 540KB of object code (loaded on demand); more than 10 times more than Jscheme on both counts. Quenniac's PS3I is a persistent server-side Scheme interpreter written in Java.

General Scheme Resources

Aubrey Jaffrey's SLIB is a comprehensive Scheme source code library.

MIT and Indiana University maintain home pages for Scheme.

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.4 55KB 29KB 69KB 1905 No separate scheme file 1.3 47KB 28KB 68KB 1888 less scheme code 1.2 42KB 26KB 64KB 1803 Better javadoc; no PrintStream 1.1 41KB 23KB 60KB 1745 Complete set of R4RS functions 1.0 40KB 22KB 57KB 1664 Passed 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

Moved the remaining Scheme code to SchemePrimitives.java. Its still the same Scheme code, but now it is read from a Java string rather than from a file. This way everything is in Java, and we don't have to worry about opening files at start-up time, and with potential file-reading security restrictions with applets. For editing convenience, the following two perl commands convert from normal text to this Java quoted String format and back again (note they need to first convert between " and \" ): perl -pe 's/"/\\"/g; s/([^\s])/"\1/ and s/\s*$/\

" +

/' perl -pe 's/\\"/"/g; s/"// and s/\

" \+//'

Version 1.3: Released April 15, 1998

Put everything in a package.

Moved everything but some macros from primitives.scm to Primitive.java . Makes for faster runtime and loading time. Only increased the number of lines of code by about 50.

to . Makes for faster runtime and loading time. Only increased the number of lines of code by about 50. Changed the stringify interface to use a single StringBuffer. Before, if you had a ten element list, stringify created ten StringBuffers, and then merged them into an eleventh. Now its all done in one StringBuffer. As a matter of fact, it might have been better for Java to provide this kind of interface for its toString method.

Version 1.2: Released April 10, 1998

Converted from PrintStream to PrintWriter. No deprecation warnings now.

Made the error routine throw a RuntimeException.

routine throw a RuntimeException. Improved javadoc comments.

Version 1.1: Released March 30, 1998.

Made (1 .2) read as (1 0.2) , not (1 . 2) .

read as , not . Added warning messages that #x and the like are not implemented.

and the like are not implemented. Added cddddr and the other 3- and 4- c[ad]r procedures.

and the other 3- and 4- c[ad]r procedures. Added force and delay .

Version 1.0: Released March 27, 1998.