Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to nicely call other JVM languages from clojure?

Tags:

clojure

Sometimes you want to glue solutions writen in different JVM languages. To do so you need to call that languages or somehow use java bitecodes. What is purest, safest, nicest way to do so in Clojure?

For example what is best way to call Scala from Clojure?

(I know that other way is easy. You can generate .class by gen-class as it writen in Can you mix the JVM languages? ie: Groovy & Clojure, but that just allow you to use clojure from other languages.)

like image 963
boucekv Avatar asked Aug 21 '12 10:08

boucekv


2 Answers

Since Clojure runs on the JVM, you can access any known class which is on your classpath out of Clojure. Here is a Scala example. To make the classpath setup and dependency management easier, use Leiningen to generate a project.

lein new clojure-scala

In the project folder, modify the project.clj and add a dependency for Scala's language libraries, and the scala-src folder to the classpath:

(defproject clj-scala "0.1.0-SNAPSHOT"
  :description "FIXME: write description"
  :url "http://example.com/FIXME"
  :license {:name "Eclipse Public License"
            :url "http://www.eclipse.org/legal/epl-v10.html"}
  :dependencies [[org.clojure/clojure "1.3.0"]
                 [org.scala-lang/scala-library "2.7.1"]]
  :compile-path "scala-src" )

Create the directory scala-src, and in that folder create the following Scala class:

class HelloWorld {
  def sayHelloToClojure(msg: String) =
    "Here's the echo message from Scala: " concat msg
}

Compile the class using scalac. Now run lein deps to download the dependencies. Launch the Clojure REPL by running lein repl. You can import the Scala class, instantiate it and call the sayHelloToClojure method.

user=> (import HelloWorld)
HelloWorld
user=> (.sayHelloToClojure (HelloWorld.) "Hi there")
"Here's the echo message from Scala: Hi there"

This is just compatible to the way you could use Scala classes and code out of Java. That can get tricky, a quote from the Frequently Asked Questions - Java Interoperability:

Using a Scala class from Java can get tricky, in particular if your Scala class uses advanced features like generics, polymorphic methods, or abstract types. Since Java doesn't have such language features, you have to know something about the encoding scheme of Scala classes.

like image 121
raju-bitter Avatar answered Nov 11 '22 22:11

raju-bitter


It is pretty easy to call other JVM languages from Clojure - all you need to do is use the Java interop syntax.

Examples:

;; import Java classes
(ns my-ns
  (:import [some.package ClassOne ClassTwo ClassThree]))

;; call a regular method on an object
(.method someObject arg1 arg2)

;; call a constructor
(ObjectToConstuct. arg1 arg2)

;; call a static method
(Math/floor 2.3)

;; Use a static field
(+ 2 Math/PI)

Basically, using these techniques you can call into any other language that creates JVM classes (which includes Java, Scala and probably most other JVM languages)

like image 7
mikera Avatar answered Nov 11 '22 22:11

mikera