by Per Bothner
scripting languages are now very visible, but they have a long history, even on the Java platform. Of languages still in use and active development today, Kawa and Netrexx are (to my knowledge) the oldest, both created in 1996. (Java was publicly launched in 1995.) Kawa appears to have been the first scripting language to be compiled directly to Java bytescodes, and is the oldest still-active functional language on the JVM. Kawa was based on a simple Scheme interpreter written by Alex Milowski, but I re-wrote it as a compiler while I worked for Cygnus Solutions, probably the first company to commercialize Free Software. Kawa is now GNU software, available under an MIT license.
Kawa is still used for a number of projects. As an example MIT App Inventor(previously Google App Inventor) for Android is built on top of Kawa.
Scripting vs programming languages
Kawa tries to combine the advantages of scripting languages with those of Java-like
Like other scripting languages, Kawa avoids boilerplate such as having to define a class and
main method. Since Kawa is an expression language, the minimal
Hello, worldprogram is just:
Macros allow syntactic extension, and can be defined in libraries just like functions. It is trivial to implement a
domain-specific languageon top of Scheme, at least as long as you use the core S-expression
datum syntax. Kawa has convenient syntactic short-hands like colon notation.
Kawa is quite dynamic: It has
eval, and a read-eval-print-loop. If you type in an expression or load a file to be evaluated, it is automatically(and quickly) compiled down to bytecode.
You don't need to specify the types of variables – but you can: Doing so helps document your program, may allow the compiler to generate faster code, and may allow the compiler to catch errors and inconsistencies.
Kawa also has the advantages a more conventional
programming language, like Java or Scala. You can compile to a
class file, which can be an application (with an automatically-generated
main), an applet, a servlet, or other specified class. It has an optimizing compiler which does decent data-flow analysis and type interface. This combined with optional type declarations make it straightforward to write code that is as efficient as Java or Scala – and many times faster than languages like JRuby or Clojure. The compiler is good at detecting and reporting errors, which avoids many painful debugging sessions. Kawa's primary visibility boundary is a sourcefile modules, which is natural and easy for both human readers and compilers.
In the rest of this article I will touch on some cool features of Kawa; maybe one of them will inspire you to try it out.
Kawa has a convenient terse syntax for object construction. For example, this creates a Swing
JButton that calls
text: "Do it!"
(lambda (e) (do-it)))
Groovy has a SwingBuilder that allows similar compact object construction. However, Kawa's is built in: It works for any
bean-like class with standard
add methods. Kawa is also more efficient, since it doesn't create a helper object. Instead the compiler translates the constructor call to code like what you'd write by hand in Java.
Of course sometimes just using the
beans naming convention isn't quite enough to yield a pleasant constructor API. For example, in the Android API you construct a tree of
View objects. Each
View constructor requires a parameter which is the current
Activity, which looks like this:
(TextView (this) text: "Hello world!")
(this) to the current
Activityis tedious boiler-plate. That is why Kawa defines some special handling so you can leave out the
(TextView text: "Hello world!")
This special handling for
View classes is not hard-wired but is defined in an Android-specific library.
Read how to build and run Android applicationsand more about Android
Kawa also has some special handling to ease JavaFX programming. This page has a simple example and up-to-date instructions. Also check out two slightly older blog articles: an introduction, and about animation.
Self-configuring web server
It is easy to write web services using Kawa. No setup or additional software is needed if using the server built in to JDK (version 6 or later). Just start Kawa like this:
kawa --http-auto-handler / appdir --http-start 8888
Here is a web page scriptthat replies back with the name of the requesting (client) host:
;; Hello world page script written in -*- scheme -*-
The script uses an XML literal with an embedded expression. Put this file in
appdir/path, and point your browser to
http://localhost:8888/path. Kawa will find the file, recognize the string
in the first line and realize it is a Scheme script, then compile (if necessary) and evaluate it, and return the result to the browser.
-*- scheme -*-
You can use the same page scripts on a servet container such as Tomcat or Glassfish, instead of using JDK's builtin server.
pure functional language uses lazy evaluation – i.e. an expression is only evaluated when the value is needed.
Impure functional languages like Scheme use strict evaluation, familiar from Java and most commonly-used languages. Kawa has a hybrid functionality: The expression
(delay E) evaluates to a
P that will evaluate the expression
E when requested. You can call
(force P) to explicitly force the resulting promise: It returns the result of evaluating
E. The expression
E is only evaluated once, and the result remembered in case
P is forced later.
delay are standard. Kawa also supports implicit forcing, as you'd find in a pure functional language: If the promise is used in a context that requires a real non-promise value, such as
(* P 2)the
P then the result is as you wrote:
(* (force P) 2). It makes it more convenient to use lazy values.
Kawa also has futures; these are also automatically forced when needed.
Meta: this post is part of the Java Advent Calendar and is licensed under the Creative Commons 3.0 Attribution license. If you like it, please spread the word by sharing, tweeting, FB, G+ and so on! Want to write for the blog? We are looking for contributors to fill all 24 slot and would love to have your contribution! Contact Attila Balazs to contribute!