Calling Clojure from Java: Why is the "new" style (clojure.java.api.Clojure) better than the "old" one (gen-class)?

Jorge D

Something is puzzling me after reading the this great answer to a related question:

There are two possibilities to share a function that I wrote in Clojure with Java developers

  • The first one is providing it in a JAR file so that they can call it as if I had written it in Java. Sounds great for Clojure advocacy.

  • The second one, the purportedly better way, requires those Java developers to use things like clojure.lang.IFn or clojure.lang.RT and invoking functions by passing their names as strings (!) instead of just calling them.

Why is the second approach "the better one"?

amalloy

You are sorta setting up a false dichotomy here. Every approach involves creating a jar file: that is just how JVM programs are distributed. But there are 3 different ways for Java code to invoke Clojure code contained in a jar:

  1. Use methods in clojure.lang.RT to initialize the runtime, load files, and then look up vars. This is the old, deprecated approach.
  2. Use methods in clojure.java.api.Clojure to look up functions and invoke them. This is the newer version of (1), and hides some of the messy stuff you could accidentally get wrong.
  3. Use gen-class in the Clojure library to define a more Java-friendly interface to the Clojure functions.

You can still do (3) - there's nothing wrong with it exactly. But gen-class is a pretty clunky tool, and except for the simplest examples like exposing a number of static methods, it's just not a lot of fun, and it's not easy to provide an API that "feels" like a Java API using Clojure.

But you know what's great at providing an API that feels like Java? Java! So what I recommend if you want to make a Clojure library easy to use in Java is to include some Java code in your Clojure library. That Java code, written by you, bridges the language gap. It accesses your Clojure code by mechanism (2) above, and presents a Java-friendly facade so the outside world doesn't have to know there's Clojure underneath.

amalloy/thrift-gen is an example of a library I wrote years ago following this approach. It would not be at all easy to write this in pure Clojure, just because traditional Java idioms are very foreign to Clojure, and it doesn't support them all very well. By writing my own Java shim instead, Java clients get a very comfortable interface to work with, and I can just write Clojure that feels like Clojure instead of a bunch of gen-class nonsense.

Collected from the Internet

Please contact [email protected] to delete if infringement.

edited at
0

Comments

0 comments
Login to comment

Related

From Java

Calling Java from Clojure

From Java

Calling clojure from java

From Java

calling clojure from Java (Clojure Interop)

From Dev

Calling a method on a Java class from Clojure

From Java

Calling java functions from Clojure

From Dev

Better way to make init a java builder class from clojure map?

From Dev

Clojure :gen-class not working in Java app

From Dev

NoClassDefFoundError calling Clojure from Java (Android, LibGDX)

From Java

Problems calling a variadic Java function from Clojure

From Dev

Calling a Java static function from Clojure

From Dev

Does :gen-class is the only way to extend Java class in Clojure?

From Dev

In clojure, how does one refer to java functions when not calling immediately?

From Dev

Can't compile Java class when calling Clojure code

From Java

Extending a Java Swing class in Clojure

From Dev

Using a Java class in the clojure repl

From Dev

Clojure: gen-class and import it in java; packages, paths, classpaths

From Dev

Documentation for old versions of Clojure java.jdbc?

From Java

Calling a very simple clojure function from Java does not work

From Dev

Problems calling a clojure function that takes a map as parameter from java

From Dev

Calling a java function with an optionally null argument from clojure

From Dev

java.lang.NoClassDefFoundError for clojure.java.api.Clojure

From Java

Passing Args to Clojure from Java

From Dev

Clojure: calling a sequence of methods on a Java object

From Java

Clojure macro for calling Java setters based on a map?

From Dev

Calling java non-static method in Clojure

From Java

"No matching ctor found" while trying to populate a Java class from Clojure

From Dev

How can I export a Java class (.jar) from Clojure?

From Dev

How to reference Enum inside a Java class from Clojure

From Java

Scala - Java = ? (Or Clojure - Java = ?)

Related Related

  1. 1

    Calling Java from Clojure

  2. 2

    Calling clojure from java

  3. 3

    calling clojure from Java (Clojure Interop)

  4. 4

    Calling a method on a Java class from Clojure

  5. 5

    Calling java functions from Clojure

  6. 6

    Better way to make init a java builder class from clojure map?

  7. 7

    Clojure :gen-class not working in Java app

  8. 8

    NoClassDefFoundError calling Clojure from Java (Android, LibGDX)

  9. 9

    Problems calling a variadic Java function from Clojure

  10. 10

    Calling a Java static function from Clojure

  11. 11

    Does :gen-class is the only way to extend Java class in Clojure?

  12. 12

    In clojure, how does one refer to java functions when not calling immediately?

  13. 13

    Can't compile Java class when calling Clojure code

  14. 14

    Extending a Java Swing class in Clojure

  15. 15

    Using a Java class in the clojure repl

  16. 16

    Clojure: gen-class and import it in java; packages, paths, classpaths

  17. 17

    Documentation for old versions of Clojure java.jdbc?

  18. 18

    Calling a very simple clojure function from Java does not work

  19. 19

    Problems calling a clojure function that takes a map as parameter from java

  20. 20

    Calling a java function with an optionally null argument from clojure

  21. 21

    java.lang.NoClassDefFoundError for clojure.java.api.Clojure

  22. 22

    Passing Args to Clojure from Java

  23. 23

    Clojure: calling a sequence of methods on a Java object

  24. 24

    Clojure macro for calling Java setters based on a map?

  25. 25

    Calling java non-static method in Clojure

  26. 26

    "No matching ctor found" while trying to populate a Java class from Clojure

  27. 27

    How can I export a Java class (.jar) from Clojure?

  28. 28

    How to reference Enum inside a Java class from Clojure

  29. 29

    Scala - Java = ? (Or Clojure - Java = ?)

HotTag

Archive