7

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.)

Community
  • 1
  • 1
boucekv
  • 1,220
  • 2
  • 20
  • 47

2 Answers2

12

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.

soc
  • 27,983
  • 20
  • 111
  • 215
raju-bitter
  • 8,906
  • 4
  • 42
  • 53
  • If you are looking for a way of interactively evaluating Scala out of Clojure - by embedding a Scala environment - that might be technically possible; but even in that case Scala will have to compile and load a class. –  Aug 21 '12 at 11:48
  • The Scala lang dependency is used since Java - and therefore Clojure - cannot instantiate Scala classes, when the Scala library is not in the classpath. – raju-bitter Aug 21 '12 at 12:48
7

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)

mikera
  • 105,238
  • 25
  • 256
  • 415