Kawaを使ってJavaとSchemeを相互に呼び出す
JavaからSchemeの呼び出し
- Main.java
import java.lang.reflect.Field; import gnu.expr.*; import gnu.lists.*; import gnu.mapping.*; import gnu.text.*; import kawa.lang.*; import kawa.standard.*; public class Main { private Scheme scheme; private Environment env; public Main() { scheme = Scheme.getInstance(); env = Scheme.builtin(); Language.setDefaultLanguage(scheme); Environment.setGlobal(env); } public Object hello(String str) throws Throwable { ModuleBody.setMainPrintValues(true); scheme.loadClass("test"); // (hello str) Object obj = LList.list2(env.getSymbol("hello"), new FString(str)); return scheme.eval(obj, env); } public static void main(String[] args) { Main main = new Main(); try { main.hello("Java"); } catch (Throwable th) { th.printStackTrace(); } } }
- test.scm
(define (hello s) (display (format #f "Hello, ~s world!\n" s))) (hello "Scheme")
- それぞれコンパイルする
- 実行
1行目は.scmファイルがロードされた時に実行されたもの。2行目がMainクラスから直接呼び出されている。
SchemeからJavaのクラスを使う
- MyModule.java
public class MyModule implements Runnable { public void run() { System.out.println("MyModule required."); } }
- MyClass.java
public class MyClass { private int d; public MyClass(int d) { this.d = d; } public int inc() { return d++; } public String toString() { return "" + d; } }
- test2.scm
(require <MyModule>) (define (run n) (let ((obj1 (make <MyClass> n))) (display obj1) (display (MyClass:inc (as <MyClass> obj1))) (display (MyClass:inc (as <MyClass> obj1))) (display obj1) (display "\n"))) (run 0)
- 実行
% java kawa.repl test2.scm
MyModule required.
0012
%
(require)でモジュールの呼び出し、(make)でオブジェクトの生成。クラスCのメソッドmethod()はC:methodという関数に対応しているようだ。
Java→Scheme→Javaの呼び出し
当然可能。Main.javaに以下のメソッドを追加して、
public Object run(int n) throws Throwable { ModuleBody.setMainPrintValues(true); scheme.loadClass("test2"); // (run n) Object obj = LList.list2(env.getSymbol("run"), n); return scheme.eval(obj, env); }
main()の中の main.hello("Java"); の下に以下の文を追加する。
main.run(1);
Main.javaとtest1.scmをコンパイルしてから実行する。
% java Main
MyModule called.
Hello, "Scheme" world!
Hello, "Java" world!
0012
1123
%
その他
Kawaは"A framework written in Java for implementing high-level and dynamic languages"ということで、Scheme以外の言語も扱える(らしい)。具体的には、Common LispとEmacs Lispが現時点で利用可能。これを利用してJEmacsの開発も行われている(が、まだ実用レベルにはなっていないようだ)。