All Scheme functions and source files are invisibly compiled into internal Java byte-codes. (A traditional interpreter is used for macro-expansion. Kawa used to also interpret “simple” expressions in interactive mode, but always compiling makes things more consistent, and allows for better stack traces on errors.)
To save speed when loading large Scheme source files, you probably want to pre-compile them and save them on your local disk. There are two ways to do this.
You can compile a Scheme source file to a single archive file.
You do this using the
The result is a single file that you can move around and
just like the
.scm source file. You just specify the name
of the archive file to the
Currently, the archive is a "zip" archive and has extension ".zip";
a future release will probably use "Java Archive" (jar) files.
The advantage of compiling to an archive is that it is simple
and transparent. A minor disadvantage is that it causes the
Java "verifier" to be run when functions are loaded from it,
which takes a little extra time.
Alternatively, you can compile a Scheme source file to a
collection of ‘
You then use the standard Java class loading mechanism to load the code.
The Java "verifier" does not need to get run, which makes
loading a little faster.
The compiled class files do have to be installed somewhere
kawa’ (or ‘
java kawa.repl’) with
-C’ flag will compile
.scm’ source file into one or more ‘
kawa --main -C myprog.scm
You run it as follows:
topname] [--main | --applet | --servlet] -C
Note the ‘
-C’ must come last, because ‘
Kawa’ processes the
arguments and options in order,
The Scheme source files we want to compile.
The directory under which the resulting ‘
.class’ files will be.
The default is the current directory.
A string to prepend to the generated class names. The default is the empty string.
The name of the "top" class - i.e. the one that contains the code
for the top-level expressions and definitions.
The default is generated from the
main method so that the resulting "top" class can
be used as a stand-alone application. See Application compilation.
The resulting class inherits from
and can be used as an applet. See Applet compilation.
The resulting class implements
and can be used as an servlet in a servlet container like Tomcat.
When you actually want to load the classes, the
must be in your ‘
You can use the
require syntax or the
load function to load the code,
by specifying the top-level class, either as a file name
outdirectory) or a class name.
E.g. if you did:
kawa -d /usr/local/share/java -P my.lib. -T foo -C foosrc.scm
you can use either:
require is preferred as it imports the definitions
my.lib.foo into the compile-time environment,
load only imports the definitions into run-time environment.
If you are compiling a Scheme source file (say ‘
that uses macros defined in some other file (say ‘
you need to make sure the definitions are visible to the compiler.
One way to do that is with the ‘
kawa -f macs.scm -C foosrc.scm
Many of the options described earlier are
relevant when compiling. Commonly used options include language selection,
--warn-xxx options, and
source-file, producing a
For example, to byte-compile a file ‘
foo.scm’ do:(compile-file "foo.scm" "foo")
This will create ‘
foo.zip’, which contains byte-compiled JVM
.classfiles. You can move this file around, without worrying about class paths. To load the compiled file, you can later
loadthe named file, as in either
(load "foo.zip"). This should have the same effect as loading ‘
foo.scm’, except you will get the faster byte-compiled versions.
Many Java projects use Ant
for building Java projects. Kawa includes a
Ant ask that simplifies compiling Kawa sources files to classes.
build.xml in the Kawa source distribution for examples.
kawac task documentation for details.
A Java application is a Java class with a special method
(whose name is
main). The application can be invoked directly
by naming it in the Java command.
If you want to generate an application from a Scheme program,
create a Scheme source file with the definitions you need, plus
the top-level actions that you want the application to execute.
For example, assuming your Scheme file is
MyProgram.scm, you have two ways at your disposal to
compile this Scheme program to a standalone application:
in the regular way decribed in the previous section, but add the
kawa --main -C MyProgram.scm
--main option will compile all Scheme programs
received in arguments to standalone applications.
in the regular way decribed in the previous section, but add the
main: #t module compile option to your module.
;; MyProgram.scm (module-name <myprogram>) (module-compile-options main: #t)
kawa -C MyProgram.scm
This way you can compile multiple Scheme programs at once, and still control which one(s) will compile to standalone application(s).
Both method will create a
MyProgram.class which you can either
load (as decribed in the previous section), or invoke as an application:
java MyProgram [
Your Scheme program can access the command-line arguments
by using the global variable ‘
or the R6RS function ‘
If there is no explicit
module-export in a module compiled
--main then no names are exported. (The default
otherwise is for all names to be exported.)
An applet is a Java class that inherits from
The applet can be downloaded and run in a Java-capable web-browser.
To generate an applet from a Scheme program, write the Scheme
program with appropriate definitions of the functions ‘
stop’ and ‘
destroy’. You must declare these
as zero-argument functions with a
Here is an example, based on the scribble applet in Flanagan’s "Java Examples in a Nutshell" (O’Reilly, 1997):
(define-private last-x 0) (define-private last-y 0) (define (init) :: void (let ((applet (this))) (applet:addMouseListener (object (java.awt.event.MouseAdapter) ((mousePressed e) (set! last-x (e:getX)) (set! last-y (e:getY))))) (applet:addMouseMotionListener (object (java.awt.event.MouseMotionAdapter) ((mouseDragged e) (let ((g (applet:getGraphics)) (x (e:getX)) (y (e:getY))) (g:drawLine last-x last-y x y) (set! last-x x) (set! last-y y))))))) (define (start) :: void (format #t "called start.~%~!")) (define (stop) :: void (format #t "called stop.~%~!")) (define (destroy) :: void (format #t "called destroy.~%~!"))
You compile the program with the ‘
--applet’ flag in addition to the
java kawa.repl --applet -C scribble.scm
You can then create a ‘
.jar’ archive containing your applet:
jar cf scribble.jar scribble*.class
Finally, you create an ‘
.html’ page referencing your applet
and its support
<html><head><title>Scribble testapp</title></head> <body><h1>Scribble testapp</h1> You can scribble here: <br> <applet code="scribble.class" archive="scribble.jar, kawa-2.0.jar" width=200 height=200> Sorry, Java is needed.</applet> </body></html>
The problem with using Kawa to write applets is that the Kawa
file is quite big, and may take a while to download over a network connection.
Some possible solutions: