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.