I found the amazing question How can I use clojure as scripting language for a Java program? which helped tremendously, but I can't figure out how to get an existing Java instance into Clojure. The use case is something really similar to AutoCad's AutoLisp. I want to let users manipulate an application with scripting so that they are free to do more without my help or input. I want to have a class that does some work
public class Testing {
public void work() {
// ....
}
}
and then add it to Clojure
public class Main {
public static void main() {
Testing t = new Testing()
IFn eval = Clojure.var("clojure.core", "eval");
System.out.println(eval.invoke(Clojure.read("(import Testing)")));
// How do i get "t" into clojure?
System.out.println(eval.invoke(Clojure.read("(.work t)")));
}
}
However I can't figure out how. I don't seem to be able to invoke def
with arguments from java. I have been fiddling with this and with documentation for a while and can't seem to figure it out.
import clojure.java.api.Clojure;
import clojure.lang.Var;
import clojure.lang.RT;
import clojure.lang.Compiler;
public class Main {
public static void main(String[] _argv) {
// Using String instead of Testing just to avoid having to
// deal with multiple files during compilation.
String s = "Hello there";
// Needed to allow creating new namespaces.
// If you ever get stuck with some functionality not working, check out
// Compiler.load - there are other bindings in there which, I guess, might be important.
// So you can either copy all the bindings here or simply use Compiler.load instead of
// Compiler.eval for script pieces that don't require bindRoot.
Var.pushThreadBindings(RT.mapUniqueKeys(RT.CURRENT_NS, RT.CURRENT_NS.deref()));
try {
Compiler.eval(Clojure.read("(ns user)"));
// def returns the var itself.
((Var) Compiler.eval(Clojure.read("(def s)"))).bindRoot(s);
Compiler.eval(Clojure.read("(println s \"in\" (ns-name *ns*)))"));
} finally {
Var.popThreadBindings();
}
}
}