My polyglot exploration

Having used Java as my main language lately, it was about time to play with some new languages. As there is a whole stack of languages that runs on the JVM now, it is hard to decide which language to play with – so I ended up playing with them all, or at least the following; JRuby, Jyhton, Groovy, Scala and Clojure.

Although they all run on the JVM, I wanted to find out how easy it actually is to combine them. My method was almost like this:

  • Install the programming language (thank you macports)
  • Find and install the correct plugin for Eclipse
  • Try execute some Java Library / code from the language
  • Try to execute something written in the language from Java
  • On some occasions I also tried to execute some of the other languages from the current language I was playing with.


    Disclaimer: I just want to share what I have learnt so far. There might be way better ways to do these things.

    Groovy
    To install Groovy I just did sudo port install groovy, whatever platform you are on, it shouldn’t be too hard.

    I also installed the Groovy Eclipse Plugin and created a new Groovy Project.

    Here is the Groovy code I wrote for calling Java

    package groovyerlingwl;
    
    import java.util.regex.Pattern
    
    class CallingJava2 {
    	
    	def pt = Pattern.compile("^foo")
    	def m = pt.matcher("foo")
    }
    
    def callingJava = new CallingJava2()
    println  "" + callingJava.m.find()
    

    To call some of my Groovy code from Java, I created a simple class:

    package groovyerlingwl;
    
    class GroovyPrinter {
    	
    	def printsomething() {
    		println "hello from Groovy"
    	}
    
    }
    

    ..and exported it as a .jar file. Interestingly enough, the .jar file now contained a groovyerlingwl/GroovyPrinter.class. To run this from Java, I had to add groovy-1.6.5.jar and asm-2.2.3.jar to the classpath. I found mine in /opt/local/share/java/groovy/lib. And all the code you need is:

    import groovyerlingwl.*;
    
    public class CallingGroovy {
    
    	public static void main(String[] args) {
    		GroovyPrinter gp = new GroovyPrinter();
    		gp.printsomething();
    	}
    	
    }
    

    Scala
    Very much like Groovy, Scala integrates simply with Java. After installing Scala, the Scala Eclipse Plugin and created a new Scala Project; I used the following to call Java:

    package erlingwlscala;
    
    import java.util.regex.Pattern
    
    object Test {
    
      def main(args: Array[String]) { 
        val pt = Pattern.compile("^foo")
        val m = pt.matcher("foo")
        println(m.find)
      }
      
    }
    

    And then I made another simple class to call from Java:

    package erlingwlscala
    
    class TestPrinter {
    
      def print_something(){
         println("Hello, from scala") 
      }
      
    }
    

    Again, I exported this to a .jar file. This also resulted in the .jar file containing a erlingwlscala/TestPrinter.class.

    To run the class from Java, I added scala-library.jar to the classpath and ran the following Java code

    import erlingwlscala.TestPrinter;
    
    public class CallScala {
    	
    	public static void main(String[] args) {
    		TestPrinter testPrinter = new TestPrinter();
    		testPrinter.print_something();
    	}
    
    }
    

    JRuby
    Again, I installed JRuby and the matching Eclipse Plugin. I created a new Ruby Project. However, make sure you choose the JRuby interpreter when running the following code:

    require 'java'
    
    include_class 'java.util.regex.Pattern'
    
    class CallingJava
      
      pt = Pattern.compile("^foo")
      m = pt.matcher("foo")
      puts m.find
      
    end
    

    Running JRuby from Java was not as easy as Groovy or Scala. However, using the JSR-223 it seems that you can run almost any scripting language from Java. So using the approach described in the article you can do the following in Java:

    import javax.script.*;
    
    public class CallJRuby {
    
    	public static void main(String[] args) throws Exception {
    		ScriptEngineManager factory = new ScriptEngineManager();
    
    		ScriptEngine engine = factory.getEngineByName("jruby");
    
    		try {
    			engine.eval("puts('Hello from JRuby')");
    		} catch (ScriptException exception) {
    			exception.printStackTrace();
    		} 
    	}
    
    }
    

    NB! Remember to download The JSR engines and include the jruby-engine.jar on the classpath. You also need to include jruby.jar on the classpath.

    Clojure

    Again, installing the suiting Eclipse Plugin. And creating a new Clojure plugin. I used the example from Clojure.org and borrowed the following code:

    (doto (new java.util.HashMap) (.put "a" 1) (.put "b" 2))
    

    To call Clojure from Java, I found this article.. First make a simple clojure program

    ; printer.clj
    (ns printer)
    
    (defn print-string [arg]
    	(println arg))
    

    Add this to your resources folder in your Java project, include clojure.jar and clojure-contrib.jar on the classpath, and run the following code:

    package erlingwl;
    
    import clojure.lang.RT;
    
    public class CallingClojure {
    	
    	public static void main(String[] args) {
    		try {
    			RT.loadResourceScript("printer.clj");
    			RT.var("printer", "print-string").invoke("hello world");
    		} catch (Exception e) {
    			e.printStackTrace();
    		}
    	}
    }
    

    Jython

    Once again, I installed Jython and downloaded the respective Eclipse Plugin. To call Java I created a new Jython project and used the following code (got it from wiki.python.org):

    from java.util import *
    r = Random()
    print r.nextInt()
    

    wiki.python.org also describes how you can use JSR-223 to run Jyhton/Python from Java. I tried the following code:

    import javax.script.ScriptEngine;
    import javax.script.ScriptEngineManager;
    import javax.script.ScriptException;
    
    public class CallJython {
    
    	public static void main(String[] args) {
    		ScriptEngine engine = new ScriptEngineManager().getEngineByName("python");
    		try {
    			engine.eval("print 'hey from python'");
    		} catch (ScriptException e) {
    			e.printStackTrace();
    		}
    	}
    }
    

    To get this to work, add jython.jar and the jython-engine.jar from The JSR engines to the classpath.

    Bonus
    I mentioned I tried to combine some of the other languages too.

    Clojure calling scala:

    (println (doto (new erlingwlscala.TestPrinter) (.print_something)))

    To do this, I added my scala application .jar to the classpath (see above where I call Scala from Java), and also I had to add the scala-library.jar.

    JRuby calling clojure:
    Here I basically followed the same approach approach as when I called Clojure from Java (see above):

    require 'clojure.jar'
    
    include Java
    
    import 'clojure.lang.RT'
    
    class CallingClojure
      
      RT.loadResourceScript("resources/printer.clj")
      RT.var("printer", "print-string").invoke("hello world")
    
    end
    

    Calling Scala from JRuby:

    My worst hack so far, I assume there are more elegant ways to do this:

    include Java
    
    SCALA_HOME =  '/opt/local/share/scala/lib/'
    require SCALA_HOME + 'scala-library.jar'
    require "scalaexport1.jar"
    
    include_class 'erlingwlscala.TestPrinter'
    
    class CallingScala
      
      printer = TestPrinter.new
      printer.print_something
      
    end
    
    About these ads

    2 Responses to “My polyglot exploration”

    1. Cory Giles Says:

      Also, you can’t call Clojure from Scala because “var” is a keyword in scala. So, you can do:

      ////

      (ns interop.test
      ;(:require )
      ;(:use )
      ;(:import )
      )

      (defn getFive [& args] 5)

      ///

      package interop

      import clojure.lang.{RT, Var, Namespace, Symbol}

      object Main {

      def call(ns: String, name: String): Object = {
      RT.loadResourceScript(ns.replace(“.”, “/”) + “.clj”)
      var fn = Var.intern(Namespace.findOrCreate(Symbol.intern(null, ns)),
      Symbol.intern(null, name))
      fn.invoke()
      }

      def main(args: Array[String]): Unit = {
      val result = call(“interop.test”, “getFive”).asInstanceOf[Int]
      println (result + 5)

      }

      }

    2. Tomás Lázaro Says:

      I know this is a year old blog but it has top 10 ranking in google.

      Just for the record, “Also, you can’t call Clojure from Scala because “var” is a keyword in scala.” is WRONG.

      You can escape “var” with back ticks and use it, it’s the same problem as “yield” which is a keyword in Scala.

      Conversion of “Java calling Clojure” into Scala:

      package erlingwl;

      import clojure.lang.RT;

      object CallingClojure {
      def main(args : Array[String]) : Unit = {
      try {
      RT.loadResourceScript(“printer.clj”)
      RT.`var`(“printer”, “print-string”).invoke(“hello world”)
      } catch {
      case e : Exception => e.printStackTrace()
      }
      }
      }

    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 )

    Google+ photo

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

    Connecting to %s


    Follow

    Get every new post delivered to your Inbox.

    %d bloggers like this: