Clojure and Java interop in a real world

烈酒焚心 提交于 2019-12-18 11:11:37

问题


I'm thinking about start using (not playing with) Clojure. Are there any useful guides? I'm not asking about lein, javac or any other 'small' manual tools. I need to know how to have Java and Clojure sources in eclipse in the same project. How to make them calling each other without compilation errors? How to configure maven? How to set up fully productive development environment? Is it even possible at the moment? What plugins may be useful? Where to start?


回答1:


I have a fully working production setup with Eclipse, Maven and Clojure that is working very nicely at the moment. Hopefully it is helpful as an example of a good polyglot setup within a Java IDE.

I don't use leiningen - Nothing against lein at all - it's very nice and ideal in a pure Clojure/CLI world. But I've found that pure Maven is nicer to work with in a polyglot Java+Clojure environment with an IDE since the tool integration is so much better. Also from an ecosystem / audience / community perspective if you want people from the Java world to be able to build your source you are going to cause a lot less confusion if you just use Maven directly.

Here is my setup:

  • Eclipse 4.2 as main IDE
  • Counterclockwise Eclipse plugin - very good, takes care of REPL, Clojure editing etc.
  • Maven used to manage all projects (I use the built in Eclipse Maven integration mostly, but occasionally use the CLI version as well)
  • cljunit used to enable JUnit tests to run on Clojure parts of the project
  • Github / Travis CI used for SCM and Continuous integration, accessed using the built-in EGit team provider in Eclipse

In terms of actually how I manage / set up the project itself:

  • I configure everything with Maven, using standard Maven directory layout. Polyglot Java+Clojure Projects typically have both src/main/java and src/main/clojure
  • Clojure is just a Maven dependency, like any other Java library.
  • I make the Clojure source directories into resource directories in the Maven setup. This means that the .clj files get bundled in any jars and can be loaded / run dynamically at runtime.
  • I usually make the entry point on the Java side with a public static void main(...) as usual, but call quite quickly into the Clojure code. See this blog post on calling Clojure from Java.

Finally some coding tips for polyglot Java+Clojure

  • I find that Java is better for low level data structures, libraries and algorithms, while Clojure is better for integrating things together and "glue" code.
  • Clojure calling Java is usually easier / more elegant than the other way round. Also it makes sense since you generally want the dependencies to flow that way (higher level code calling lower level code)
  • If you make all your Java classes immutable, they play very nicely in a Clojure world with minimal effort.
  • Sometimes it is worth making one or more of your Java classes implement some of the Clojure interfaces, particularly clojure.lang.IFn for example. This way your Java objects can act as first class functions in Clojure code.

Here's an example project that mixes Java and Clojure source:

  • https://github.com/mikera/enlight

I also wrote a small library (clojure-utils) that includes some example code for calling Clojure from Java, which you may find useful.




回答2:


Despite your tone about leiningen, I recommend looking at it. Leiningen supports Java compilation, so combining java and clojure sources in one project isn't a problem.

The Counterclockwise plugin, the clojure plugin for Eclipse, can work with leiningen project files (project.clj). So within Eclipse you have dependency management and java compilation all handled for you by defining the right things in project.clj, without the need to install leiningen separately or execute commands from the command line.

In the project.clj set :java-source-paths, like for example:

:java-source-paths ["src/main/java"] 

In package src/main/java put a class Foo:

package main.java;

public class Foo {
    public static final String value = "Michiel";
}

Somewhere in a clojure source file define this function and "Michiel" will be printed when it is called:

(defn foo
  "I don't do a whole lot."
  []
  (println (main.Foo/value)))

Further reading:

  • http://leiningen.org/
  • http://code.google.com/p/counterclockwise/



回答3:


You could also try the framework "Funky". It will completly seperate you Clojure and Java code . Just have a look at https://github.com/windler/Funky



来源:https://stackoverflow.com/questions/14013725/clojure-and-java-interop-in-a-real-world

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!