Looks like the title for this is backwards if I understand the intent, 
should be calling Clojure from Java, right?

Java code is going to invoke methods on classes (that's all it knows how to 
do). You have several options:

1) Use the Clojure Java API to invoke the Clojure runtime - here you're 
leveraging the Clojure runtime's Java impl core to call into Clojure (Stu's 
example)
2) Use protocols, records, and/or genclass to actually produce Java classes 
(your example, I think). 
3) Define your interface as a set of Java interfaces. Implement this 
interface in Clojure. You will need a small amount of glue code to provide 
the API impl (some kind of a factory to give you the impl of the Java 
interface - either written in Java or using #1). 

#1 is straightforward but tedious - it's really only worthwhile if you have 
a small amount of this code and hide the use of it.
#2 has significant downsides - needing to compile everything, all methods 
are just going to take/return Java Objects, no javadoc on apis,  etc. 
#3 has advantages in all those areas. You write your Java interface where 
you can best write it ... in Java (with Javadoc, and Java interfaces, and 
all the niceties Java users want). IDEs can autocomplete on the Java 
interfaces. You don't have to AOT - factories can reify or load protocol 
instances as needed as they return objects. You can even reload internal 
vars with a connected REPL without restarting the app.

The last does take a bit of planning to set up - you need API code (in 
Java), and Clojure code that relies on that Java code. lein makes it pretty 
trivial to put those in one project and compile in that order.

I pushed an example up here:

https://github.com/puredanger/clojure-from-java

It defines a Java interface (java/cfj/Event.java 
<https://github.com/puredanger/clojure-from-java/blob/master/java/cfj/Event.java>),
 
a static helper to hook the Clojure (java/cfj/Support.java 
<https://github.com/puredanger/clojure-from-java/blob/master/java/cfj/Support.java>),
 
which uses the Clojure Java API to load the Clojure instance in 
clj/core/cfj.clj 
<https://github.com/puredanger/clojure-from-java/blob/master/src/cfj/core.clj>. 
Just `lein uberjar` and you're done. Use the Support API from Java as any 
other Java class. No AOT required.



On Sunday, June 9, 2019 at 9:53:56 PM UTC-5, eglue wrote:
>
> I've been stalking Clojure for a while but now doing it professionally 
> full-time (woo hoo!).
>
> I saw a Stuart Halloway tweet responding to someone who'd found it a 
> "soul-crushing, miserable experience."
>
> I had a similar miserable experience and figured it was just me, but am 
> now suspecting that's not the case. (Happy to be shown the light however.)
>
> Stuart H posted https://github.com/stuarthalloway/clojure-from-java 
> <https://www.google.com/url?q=https%3A%2F%2Fgithub.com%2Fstuarthalloway%2Fclojure-from-java&sa=D&sntz=1&usg=AFQjCNFxHASS9MQ07WZ5St1GE9g1WckHFg>
>  to 
> demonstrate the ease of Java consuming Clojure, but I find it far more 
> important to be able to *compile* Java against Clojure interfaces not 
> invoke it dynamically from Java....because dynamic invocation from Java is 
> unwieldy to the point of it being a likely deal breaker for any Java shop. 
> Dynamically loading classes and invoking methods.... c'mon, no one's going 
> to ask their Java devs to do this.
>
> If Clojure doesn't have a good compile-time consumption story for Java 
> consumers, I think that's a loss. (Even if it is just providing better docs 
> or archetype/bootstrap examples in this regard.) Because otherwise Java 
> code bases around the world could be eaten away by (compiled) Clojure from 
> the inside out, giving Java dev teams enough time to be overtaken by the 
> miracle that is Clojure.
>
> Inspired by Stuart's example, I was successful in putting together a quick 
> build to achieve this ideal: https://github.com/atdixon/clojure-from-java 
> <https://www.google.com/url?q=https%3A%2F%2Fgithub.com%2Fatdixon%2Fclojure-from-java&sa=D&sntz=1&usg=AFQjCNG0DEccFtsm0Norw4jQ_qw-dezdZw>
>
> However, I have a few open questions:
>
> - when I tried to AOT only the public-facing clojure code that I needed to 
> compile against, I found out at runtime that this wasn't going to work. 
> Dynamic clojure code was loading my same types into DynamicClassLoader and 
> when my statically-compiled, root-class-loaded code was getting executed 
> the ClassCastExceptions of course were flying. So am I right to think that 
> you have to AOT everything in order to do this right?
> - IDE support (for me, Cursive) "works" but is non-ideal; you have to 
> manually compile the dependee/Clojure jar, then Cursive will let you 
> execute Java code against the manually aot-compiled Clojure code 
> - AOT producing generics/generic types doens't seem to be part of any of 
> this... is this a lacuna in the Clojure AOT space, are there libs that can 
> help here?
>
> This story ^^, if made easier, seems to me would boost Clojure adoption in 
> Java/JVM shops.
>
> What am I missing?
>
>
>

-- 
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en
--- 
You received this message because you are subscribed to the Google Groups 
"Clojure" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to clojure+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/clojure/810d6af0-316d-40d3-9ab0-eab1c1ccf787%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to