Invoking Clojure code from Java

I often see people trying to call Clojure code from Java and having some trouble doing this. So I decided to write a quick utility to do this (inspired by Rich Hickey’s Lightening Talk), and provide a simple example.

The idea is that we use clojure.lang.RT to get access to the key functions that we need to call compile / Clojure code. We do this by setting up some static final variables in Java of type clojure.lang.Var, which we can then invoke to get the required behaviour from Clojure. Setting up these vars looks like this:

import clojure.lang.RT;
import clojure.lang.Symbol;
import clojure.lang.Var;
...
public class Clojure {
 ...
 public static final Var REQUIRE=RT.var("clojure.core", "require");
 ...
}

Once we have the REQUIRE var available, we can invoke it to load any Clojure namespace we need, using code like below:

public static Object require(String nsName) {
  return REQUIRE.invoke(Symbol.intern(nsName));
}

static {
  require("my.special.namespace");
}

I’ve wrapped all this functionality up into a little utility class mikera.cljutils.Clojure, so you can write quick and easy Java apps that call into Clojure as below:


import mikera.cljutils.Clojure;

public class DemoApp {
  public static void main(String [] args) {
    String s = "(+ 1 2)";
    System.out.println("Evaluating Clojure code: "+s);
    Object result=Clojure.eval(s);
    System.out.println("=> "+ result);
  }
}

The utility is available here:

- GitHub site: https://github.com/mikera/clojure-utils

- Compiled version on Clojars: https://clojars.org/net.mikera/clojure-utils

About these ads

7 Comments

  1. clojurian said,

    December 27, 2012 at 7:06 pm

    Interesting post. It would be cool if the official clojure.jar provided some Java-to-Clojure interop classes. While the direction Clojure->Java is probably more common, it would certainly help to make Clojure more popular if such standard classes existed.

    • Mike said,

      December 28, 2012 at 1:18 am

      Good idea, something like this would probably make sense in core Clojure. Guess it is a tricky call – how far do you go in providing “convenience methods” since everything is already possible?

  2. clojurian said,

    December 28, 2012 at 11:21 am

    Suppose you have an awesome Clojure library that you want to use from Java. You could use your Clojure.eval() but it would be nicer to import functions from Clojure into the world of Java and then use them as if they were actual Java objects:

    ClojureFn someCoolClojureLibraryFunction = Clojure.getFunction( “namespace”, “functionname” );

    So that you can just call
    someCoolClojureLibraryFunction.call();

    Another possibility could be that you can retrieve an entire namespace as an object and all functions in that namespace are static methods associated with that namespace-object.

    ClojureNS coolLib = Clojure.getNamespaceObject( “namespace” );
    coolLib.talk_like_a_pirate();

    This (and your Clojure.eval method) are probably the most important parts for Java->Clojure interop.

    • Mike said,

      December 28, 2012 at 11:55 am

      To some extent you can already do the first approach with the IFn interface and clojure-utils:

      import clojure.lang.IFn;
      ….
      IFn coolFun = Clojure.eval(“my.namespace/my-cool-function”);
      coolFun.invoke(param1,param2);

      • clojurian said,

        December 28, 2012 at 2:18 pm

        Cool. That wasn’t so obvious to me ;)

        Maybe it’s just the “eval is evil” mentality that I have aquired from using other programming languages that prevents me from thinking that eval() is okay for lisp-like languages.

        Your code and your solution are simple but powerful. So it may be a good idea to include it in the official clojure.jar so that Java people will know that they can easily call Clojure code from Java if they need to.

        It’s certainly not much code that is required for Java->Clojure interop but you first need to understand Clojure at a deeper implementation level before you can write an interoperator like your Clojure class. And having an official interoperator could be a good thing. I’d be interested in what other people think about this.

  3. piotrek said,

    January 27, 2013 at 4:38 pm

    in the presentation, Rich Hickey uses REQUIRE.invoke(Symbol.intern(“datomic.query”));
    he does the same for “datomic.peer” and “datomic.function” but not for e.g. “datomic.common” (which is also used in with RT.var). why? when ‘intern’ should be called and when not?

    • mikera7 said,

      February 4, 2013 at 2:36 am

      intern is just used to create an interned symbol. it’s good practice whenever you want a symbol that is likely to hang around and get re-used a lot (avoids creating new instances all the time).


Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Connecting to %s

Follow

Get every new post delivered to your Inbox.

Join 185 other followers

%d bloggers like this: