views:

396

answers:

3

Hi

It's just a stupid question that I had this morning : Can we use Scala classes from clojure ?

Because if the answer is yes, I'll definetly learn Clojure ^^

+14  A: 

Scala classes are Java classes and you can use Java classes from Clojure quite conveniently.

Have fun learning Clojure. :-)

Michał Marczyk
And Cloujre classes (created using `gen-class` and `deftype/defrecord`) can also be used from Scala. It's all bytecode underneath.
abhin4v
The problem is that the Scala methods have ugly and verbose names in Java ("+" becomes $plus...), is it the same thing with Clojure ?
Aymen
Unfortunately, yes. Like `blank?` becomes `blank_QMARK`. That is because Java (or JVM?) does not support such characters in the identifiers.
abhin4v
With `gen-class` or, say, `definterface` + `deftype` (or `defrecord`) you can call your methods whatever you like. Note that Clojure itself only uses classes as an implementation detail (at a low level the user doesn't necessarily need to know about) and (at a high level) in interop scenarios. Pure Clojure code is built around totally different concepts than Java code; if you want to mix Clojure and Java / Scala class-based code, you'll likely get the best mileage by implementing solid chunks of functionality in Clojure and then exposing wrapper classes (which is fairly straightforward to do).
Michał Marczyk
@abhin4v: Sure, but if you actually wanted to call a Clojure function from Java, you'd do something like `clojure.lang.RT.var("clojure.core", "even?").invoke(2)`, avoiding the nasty munging. (That's equivalent to `(#'clojure.core/even? 2)`; alternatively, you could extract the function from the Var with `.get` and `.invoke` that.)
Michał Marczyk
Ok thanks a lot ^^
Aymen
@Aymen: You're welcome. Happy hacking!
Michał Marczyk
@MichałMarczyk: Didn't know that. Thanks for the info.
abhin4v
This answer should not be accepted - I think it shows a complete lack of understanding of what lies in store, even if it's true that "scala classes are just java classes"
oxbow_lakes
Although maybe I'm wrong - @Michal - can you ask Clojure to generate lambdas of a specific type?
oxbow_lakes
@oxbow_lakes: I would point out that to the degree that Clojure-Scala interop would be "poor" because of Scala's "generics" / type variance etc., Java-Scala interop would be at least equally poor (and probably much more so because of macros). At any rate, I believe that Scala functions are instances of classes which have at least one `apply` method (there might be more, with different signatures) and which mix in the appropriate `FunctionN` trait (with `N` being a digit). Unless I am missing some complication of fundamental importance, I can't see why you couldn't generate them from Clojure.
Michał Marczyk
@oxbow_lakes: As for generics in general, Scala's compiler is able to treat them in a meaningful way, but they still disappear from the generated bytecode through type erasure, because there is of course no JVM support. This has the good side of allowing Java code to instantiate complex Scala types, albeit in a clumsy manner, with many conveniences unavailable; doing the same from Clojure might actually be easier, since you could macro away many patterns which would be extremely tedious in Java. However, perhaps the *main point* is that language interop normally happens on a higher level.
Michał Marczyk
@oxbow_lakes: For example, if Scala had a great implementation of 7zip compression, I might call out to that from Clojure to avoid writing my own version. Or if it had a great parser for some kind of input I was interested in, it could be easier to write a converter to turn the Scala data structures returned by that parser into Clojure data structures than it would be to reimplement the whole parser (I've done something similar with ANTLR). In fact, this is what I understood the question to mean (note that it's about "using Scala classes from Clojure" and not "writing Scala code in Clojure").
Michał Marczyk
@oxbow_lakes: At this level, interop should be not only possible, but reasonably convenient. ("Should" here means that I think that it probably is, but also that any JVM language making claims to having great Java interop should make sure that it is.) Interop in the sense of switching languages mid-sentence might be a different story.
Michał Marczyk
@oxbow_lakes: Anyway, thanks for raising an interesting point. The above is my initial take at answering it, but I know I'll be thinking about it some more.
Michał Marczyk
+9  A: 

Scala classes, yes. Scala singleton objects, with the same year signature as from Java. Scala traits, no. Scala implicits, hah, you jest!

So the experience may range from "ok", if it's just your classes, to very disagreeable, in the case of Scala collections, for instance.

Daniel
I don't know about implicits, but traits are interfaces, possibly coupled with helper classes. Daniel Spiewak has [a nice write-up](http://www.codecommit.com/blog/java/interop-between-java-and-scala) on Scala/Java interop including a section on using traits from Java; judging from that, it gets tedious for traits which are not "pure abstract", but in Clojure much of that tedium -- perhaps nearly all -- could be abstracted away with macros.
Michał Marczyk
+2  A: 

Worth saying that Scala classes which take function parameters, such as:

Option.map(f : A => B)

Are unlikely to be very useable from Clojure, because the Clojure compiler will not turn Clojure lambdas into instances of scala.FunctionN. I'm with Daniel - I think interop will be poor.

oxbow_lakes
I'm pretty sure you could use macros to solve the usability issue - basically get the macro to wrap the Clojure lambda into a scala.functionN?
mikera