| From | Sent On | Attachments |
|---|---|---|
| Ray Myers | Jun 27, 2008 5:32 pm | |
| Chas Emerick | Jun 28, 2008 7:20 am |
| Subject: | Calling Clojure from Java (Shortcuts) | |
|---|---|---|
| From: | Ray Myers (ray....@gmail.com) | |
| Date: | Jun 27, 2008 5:32:27 pm | |
| List: | com.googlegroups.clojure | |
Hello,
Evaluating arbitrary Clojure code from Java seems to be a common stumbling block, so I put together a simple utility to wrap the process. Please let me know if the attached code is a reasonable way to do this.
One issue is that the callers of runClosureScript() all share and modify the same lexical environment. Is it possible to prevent this?
Cheers, -- Ray Myers
import java.io.StringReader; import java.util.HashMap; import java.util.Map; import java.util.Map.Entry;
import clojure.lang.Associative; import clojure.lang.Binding; import clojure.lang.Compiler; import clojure.lang.Namespace; import clojure.lang.PersistentHashMap; import clojure.lang.RT; import clojure.lang.Symbol; import clojure.lang.Var;
public class ClojureScriptRunner {
public static Object runClosureScript(Map<String, ? extends Object> bindings, String script) throws Exception { try { new Binding<String>(script); Namespace ns = (Namespace) RT.CURRENT_NS.get(); Associative mappings = PersistentHashMap.EMPTY; mappings = mappings.assoc(RT.CURRENT_NS, RT.CURRENT_NS.get()); for (Entry<String, ? extends Object> e : bindings.entrySet()) { String varName = e.getKey(); Symbol sym = Symbol.intern(varName); Var var = Var.intern(ns, sym); mappings = mappings.assoc(var, e.getValue()); } Var.pushThreadBindings(mappings); return Compiler.load(new StringReader(script)); } finally { Var.popThreadBindings(); } }
// Example public static void main(String[] args) throws Exception { Map<String, Integer> bindings = new HashMap<String, Integer>(); bindings.put("a", 2); bindings.put("b", 3); System.out.println(runClosureScript(bindings, "(+ a b)")); // prints 5 }





