Jscheme
A Java-based dialect of Scheme

by Ken Anderson, Tim Hickey, Peter Norvig
29 March 2002
Jscheme is
  • a dialect of Scheme with a very simple interface to Java, called the Javadot notation (see below).
  • a reference implementation for this dialect (implemented in Java, bootstrapped with Jscheme).
See the Jscheme is easy to download and has a very generous licence.

It implements all of R4RS Scheme except that continuations can only be used as escape procedures and strings are not mutable.

For more info, see a recent talk on Jscheme from the MIT Dynamic Languages Seminar.

Jscheme is an open source project hosted at sourceforge.net.

SourceForge Logo

HTML access to the CVS sources is available from the Jscheme sourceforge site You can download the source code directly using anonymous CVS as follows:
  % cvs -d:pserver:anonymous@cvs.jscheme.sourceforge.net:/cvsroot/jscheme login
   (when prompted for a password for anonymous, simply press the Enter key)
  % cvs -z3 -d:pserver:anonymous@cvs.jscheme.sourceforge.net:/cvsroot/jscheme co jscheme
You may also browse through the jscheme directory directly, (but these sources may be slightly out of date...)

The Java Dot Notation

The key innovation behind Jscheme is the Java Dot Notation which allows a simple and almost transparent access to the methods, contructors, and fields of all Java classes on the classpath.

SyntaxType of MemberExample
"." at the end constructor(Font. NAME STYLE SIZE)
"." at the beginning instance member(.setFont COMP FONT)
"." at beginning and "$" at the end instance field (define (mycar x) (.first$ x))
(define (myset-car! x y) (.first$ x y))
"." only in the middle static member(Math.round 123.456)
".class" suffix Java classFont.class
"$" at the end static field Font.BOLD$
(set! U.useJavaSyntax$ #t)
"$" in the middle inner classjava.awt.geom.Point2D$Double.class
"$" at the beginning packageless class$ParseDemo.class
"#" at the end allow private access (.name$# (Symbol.# "abc"))

The import statement can be used as in Java to allow the package name to be omitted from classes. The examples in the table above assume that the following classes have been imported:

The following code creates a window with a close button. Java literals are colored with constructors in fuchsia, instance and static methods in red, and class and instance variables in green:

;; Jscheme example 
(import "java.awt.*")
(import "java.awt.event.*")


(define win (Frame. "Hello"))
(define b (Button. "Goodbye"))
(.add win (Label. "Hello")
      BorderLayout.NORTH$)
(define p (Label. 
  (string-append "sin(PI) = " 
    (Math.sin  Math.PI$))))
(.add win b)
(.add win p  BorderLayout.SOUTH$)
(.addActionListener b
  (Listener. (lambda (e)
    (.hide win))))
(.pack win)
(.show win)
(.println System.out$ "Done")
/* Java example */
import java.awt.*;
import java.awt.event.*;
public class Demo {
static public void main(String[] args) {
  final Frame win = new Frame("Hello");
  Button b = new Button("Goodbye");
  win.add(new Label("Hello"),
          BorderLayout.NORTH);
  Label p = new Label(
   "sin(PI) = "+ 
     Math.sin(Math.PI));
  win.add(b);
  win.add(p,BorderLayout.SOUTH);
  b.addActionListener(
    new ActionListener(){
      public void actionPerformed(ActionEvent e) {
        win.hide();}});
  win.pack();  win.show();  
  System.out.println("Done");}}

Jscheme defines some helper classes for easily specifying event handlers. For Java 1.2, the expression (Listener. (lambda (e) EXPR)) returns an object which implements all of the Java 1.2 Listener interfaces. The action for all methods of these interfaces is to call the lambda expression on the event. Jscheme also provides constructors for Java1.1 listeners (Listener11. F) and Java1.1+Swing (Listener11swing. F). If the code should run under Java1.1, then the Listener11 constructor should be used instead, as we have done here.

The Jscheme code becomes even simpler if we use a high level GUI library, JLIB (written in Jscheme). In the example below, the JLIB procedures are written in blue

;; Jscheme/JLIB example 
(import "java.awt.*")
(import "java.awt.event.*")
(define win (window "Hello"
  (border
    (north (label "Hello"))
    (center (button "Goodbye" (action (lambda(e) (.hide win)))))
    (south (label (string-append "sin(PI) =" (Math.sin Math.PI$)))))))
(.pack win)
(.show win)
(.println System.out$ "Done")