atom feed2 messages in com.googlegroups.clojureCalling Clojure from Java (Shortcuts)
FromSent OnAttachments
Ray MyersJun 27, 2008 5:32 pm 
Chas EmerickJun 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 }