Re: Calling Java from Clojure

2019-06-21 Thread eglue
This is a good clarification.

I found that when I tried to exclude some AOT stuff from the jar you can 
get into a situation where Clojure will dynamically produce a class that is 
already statically-produced at the root classloader and then you'll hit 
ClassPathExceptions when you try to pass these things around.

For example I had dynamic (non-AOT'd) code paths using a defrecord, for 
which a .class file was generated dynamically. So if I kept the AOT'd 
defrecord, as well, I'd have two classes one in the root classloader and 
one from dynamic clojure (DynamicClassLoader). 

So if what you're saying is possible, I think you will have to show quite a 
bit of careful surgery to avoid these kinds of problems?

On Thursday, June 20, 2019 at 11:13:41 PM UTC-5, Didier wrote:
>
> Option #1 and #3 are very much the same, just that Option #3 creates a 
> Java layer on top, instead of having everything coupled to the Clojure Java 
> APIs directly.
>
> When you go with Option #2, you do not have to AOT everything, but AOT is 
> transitive. So as you AOT the gen class, all code it requires and all code 
> they in turn require will also be AOT. You can post-process the AOT when 
> jaring, and only include the gen-class .class files in the Jar and not the 
> dependencies, but that's more work.
>

-- 
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/02a72bb0-9a6f-4574-9134-2d8983db8b81%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


Java Interop on steroids?

2019-06-20 Thread eglue
Don't get me wrong, I'm as much against types as the next R̶i̶c̶h̶ 
̶H̶i̶c̶k̶e̶y̶  guy.

However -- there are many popular Java frameworks that love to reflect on 
their annotations and their generic type signatures.

To name a heavyweight: Spring. But also, of late: big data frameworks, many 
written in Java, love reflecting on generic type signatures. My org is 
looking at Beam and Flink, for example.

These frameworks use types not for the static checking really but as 
parameters governing their own dynamic behavior. For example, Spring will 
use types at runtime to simply match objects to where they should be 
dynamically injected. Beam will look at your type signatures and do runtime 
validations to ensure it can process things appropriately. Of course this 
is unfortunate, using types this way, when it is all really just data. 
Clojure does -- or would do -- it better, simpler, directer, and all of 
that.

Yet we would like to leverage these frameworks. Or rather, we must for 
various pragmatic and business reasons.

And any time we need to "communicate" to these frameworks "through" their 
desired fashion of generic types and annotations, we can, of course, create 
the appropriate .java files to represent what is needed (and then do the 
invocation back to Clojure via IFn.invoke or Compiler.eval, etc). Yes, this 
works.

However this is quite tedious because in these frameworks I mentioned you 
end up having to create these Java files quite a bit. For example, when 
expressing a streaming data pipeline to Beam, you may specify multiple 
transforms, each a function with its own type signature.

A little searching and it seems Clojure has shied away from generating 
generic type information in places where it could offer this capability. 

For example, in `proxy` ... or I suppose also in `gen-class`, `reify`, and 
other dynamic bytecode generation features of Clojure.

However it seems to me that `proxy` (and these others) could allow one to 
pass in a representation of desired type arguments, annotations, etc. and 
then we could remain in Clojure to interop with these popular frameworks.

I respect Clojure's efforts to keep its core small and wait for worthy 
features to prove themselves.

So my question is not when is Clojure going to do this, but rather:

Are there any precedents in the community for someone building out the kind 
of richer Java interop that I'm nodding toward here?

For example, does anyone know of an attempt out there to build a `proxy` 
plus-plus, that would allow one to extend a generic class with provided 
type parameters and have this metadata properly rendered in the bytecode 
that proxy produces?

If not, as a practical and hopefully quick and workable solution, I was 
thinking it'd be possible to take the bytecode emitted by proxy and re-run 
it through ASM to create a *new* class with simply the proxy-produced class 
bytes filled-in with the desired, provided type parameters. I bet this 
could be sufficient and fast, with the slight overhead of the extra class.

To do this, I think I'd need access to these proxy-made bytes... either by 
having proxy answer them somehow, or offering a hook to contribute to the 
defined bytecode before it is committed to the classloader, or by having 
DynamicClassLoader have these bytes on hand for inquiring parties, or 
something else along these lines. This would likely be something that 
Clojure core would have to expose .. correct me if I'm wrong.

Would love to hear any other immediate thoughts on this.

I think once you realize that this generic type information is not even 
being used for "static typing" by these frameworks but rather as an (albeit 
poor) means to receive semantic information from their clients (as 
parameters to govern their own dynamic behavior), then the need/value of 
being able to remain in Clojure and communicate to these libraries through 
generic params and annotations perhaps becomes more understandable..









-- 
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/128dd732-b79e-4c35-999f-691cdc42512b%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


Re: Calling Java from Clojure

2019-06-10 Thread eglue
> I find the glue code is actually small in practice (I've done a couple of 
real systems this way). This particular example is a little weird because 
it's just making a domain object, but generally you're writing the glue to 
provide a factory method for a facade. Below the facade, the Clojure code 
can make new objects just fine, so you're staying in Clojure for the rest 
of it.

Very helpful, thanks!

On Monday, June 10, 2019 at 8:20:44 AM UTC-5, Alex Miller wrote:
>
>
> On Mon, Jun 10, 2019 at 12:04 AM eglue > 
> wrote:
>
>> This is great, Alex, thanks. (Sorry, I deleted from underneath you and 
>> reposted to fix the title before I saw your reply...)
>>
>> The latter option, writing interfaces and classes in Java and calling w/ 
>> the glue code is a great option.
>>
>> However one big motivator for people moving from Java to langs like Scala 
>> and Kotlin is being able to implement those bean/record types, eg, with 
>> such little fanfare & boilerplate (eg in Clojure, using defrecord is so 
>> concise). 
>>
>
> The problem with wanting the Clojure-y version from Java is that those 
> interfaces are generic and weird from the Java side. So either you get 
> bean-like code familiar to Java users or generic collection/keyword 
> interfaces that will be weird to use from Java. I heard your goal as "be 
> friendly from Java", which means, making bean-like interfaces. On the 
> Clojure side, it's pretty easy to macro-ize the creation of those over 
> defrecords or whatever, so it could still be  a lot less macro work, just 
> depends how far you want to go with it. You don't get all the benefits of 
> Clojure from Java; you have to be in Clojure for the many related design 
> decisions to compound together. There's no magic solution to that (other 
> than "just use Clojure" :).
>  
>
>> And you can sometimes end up with a handful of these, so the 'glue code' 
>> isn't quite so small. Also gen-class and definterface I find similarly 
>> nice. 
>>
>
> I find the glue code is actually small in practice (I've done a couple of 
> real systems this way). This particular example is a little weird because 
> it's just making a domain object, but generally you're writing the glue to 
> provide a factory method for a facade. Below the facade, the Clojure code 
> can make new objects just fine, so you're staying in Clojure for the rest 
> of it.
>  
>
>> I wonder if there's a path to improve what you're calling option #2. 
>> Specifically the needing to AOT compile *everything*. It seems I should 
>> only have to AOT/precompile the surface area that my Java consumer wants to 
>> link with. At runtime perhaps there'd be some creative way to leave out the 
>> AOT classes (which would just have been used for static-time compiling) and 
>> when the JVM tries to load those classes some agent could interject and do 
>> the dynamic Clojure loading?
>>
>
> Seems like you're taking the hardest path and trying to make it harder. I 
> just don't see the point in running at this one, sorry. My experience is 
> that the approach above works great and has none of these issues.
>  
>
>>
>>
>> On Sunday, June 9, 2019 at 11:21:28 PM UTC-5, Alex Miller wrote:
>>>
>>> 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 n

Re: Calling Java from Clojure

2019-06-09 Thread eglue
This is great, Alex, thanks. (Sorry, I deleted from underneath you and 
reposted to fix the title before I saw your reply...)

The latter option, writing interfaces and classes in Java and calling w/ 
the glue code is a great option.

However one big motivator for people moving from Java to langs like Scala 
and Kotlin is being able to implement those bean/record types, eg, with 
such little fanfare & boilerplate (eg in Clojure, using defrecord is so 
concise). And you can sometimes end up with a handful of these, so the 
'glue code' isn't quite so small. Also gen-class and definterface I find 
similarly nice. 

I wonder if there's a path to improve what you're calling option #2. 
Specifically the needing to AOT compile *everything*. It seems I should 
only have to AOT/precompile the surface area that my Java consumer wants to 
link with. At runtime perhaps there'd be some creative way to leave out the 
AOT classes (which would just have been used for static-time compiling) and 
when the JVM tries to load those classes some agent could interject and do 
the dynamic Clojure loading?


On Sunday, June 9, 2019 at 11:21:28 PM UTC-5, Alex Miller wrote:
>
> 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=D=1=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 Javabecause 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 ha

Calling Clojure *from* Java

2019-06-09 Thread eglue
Regarding calling Clojure **from** Java...

I saw a Stuart Halloway tweet responding to someone who'd found this 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 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 Javabecause 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

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/2fcaf22d-2179-4de0-b25b-70ac1b9db58c%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


Re: Calling Java from Clojure

2019-06-09 Thread eglue
Oops, this should have be titled "Calling Clojure from Java" ... the 
interop with Clojure calling Java is obviously well-worn and solid.

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 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 Javabecause 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
>
> 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/0e493ca3-b07d-4582-8850-57da5d0132e4%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


Calling Java from Clojure

2019-06-09 Thread eglue
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 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 Javabecause 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

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/2d16d197-dff5-4417-9ea7-d85e4baa00a6%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.