【问题标题】:Clojure and Java interop in a real world现实世界中的 Clojure 和 Java 互操作
【发布时间】:2012-12-10 10:13:25
【问题描述】:

我正在考虑开始使用(不玩)Clojure。有什么有用的指南吗?我不是在询问 lein、javac 或任何其他“小型”手动工具。我需要知道如何在同一个项目中的 eclipse 中拥有 Java 和 Clojure 源代码。如何让他们在没有编译错误的情况下互相调用?如何配置maven?如何建立完全生产的开发环境?目前甚至可能吗?哪些插件可能有用?从哪里开始?

【问题讨论】:

    标签: java eclipse jakarta-ee maven clojure


    【解决方案1】:

    我有一个完整的 Eclipse、Maven 和 Clojure 生产设置,目前运行良好。希望它可以作为 Java IDE 中良好的多语言设置示例有所帮助。

    我不使用 leiningen - 一点也不反对 lein - 它在纯 Clojure/CLI 世界中非常好和理想。但我发现纯 Maven 更适合在带有 IDE 的多语言 Java+Clojure 环境中使用,因为工具集成要好得多。同样从生态系统/受众/社区的角度来看,如果您希望来自 Java 世界的人能够构建您的源代码,那么如果您直接使用 Maven,那么您会减少很多混乱。

    这是我的设置:

    • Eclipse 4.2 作为主要 IDE
    • Counterclockwise Eclipse 插件 - 非常好,负责 REPL、Clojure 编辑等。
    • Maven 用于管理所有项目(我主要使用内置的 Eclipse Maven 集成,但偶尔也会使用 CLI 版本)
    • cljunit 用于使 JUnit 测试能够在项目的 Clojure 部分上运行
    • Github / Travis CI 用于 SCM 和持续集成,使用 Eclipse 中内置的 EGit 团队提供程序访问

    就我如何管理/设置项目本身而言:

    • 我使用标准 Maven 目录布局使用 Maven 配置所有内容。 Polyglot Java+Clojure 项目通常同时具有 src/main/javasrc/main/clojure
    • Clojure 只是一个 Maven 依赖项,与任何其他 Java 库一样。
    • 我将 Clojure 源目录设置为 Maven 设置中的资源目录。这意味着.clj 文件捆绑在任何 jar 中,并且可以在运行时动态加载/运行。
    • 我通常像往常一样使用public static void main(...) 在Java 端创建入口点,但调用Clojure 代码的速度非常快。请参阅calling Clojure from Java 上的此博客文章。

    最后是多语言 Java+Clojure 的一些编码技巧

    • 我发现 Java 更适合低级数据结构、库和算法,而 Clojure 更适合将事物集成在一起和“粘合”代码。
    • Clojure 调用 Java 通常比反过来更容易/更优雅。这也是有道理的,因为您通常希望依赖项以这种方式流动(高级代码调用低级代码)
    • 如果您将所有 Java 类都设置为不可变类,那么它们在 Clojure 世界中的表现就非常好,而且工作量很小。
    • 有时值得让一个或多个 Java 类实现某些 Clojure 接口,尤其是 clojure.lang.IFn。这样,您的 Java 对象就可以在 Clojure 代码中充当第一类函数。

    这是一个混合了 Java 和 Clojure 源代码的示例项目:

    我还编写了一个小型库 (clojure-utils),其中包含一些用于从 Java 调用 Clojure 的示例代码,您可能会发现这些代码很有用。

    【讨论】:

    • 如果我错了,请纠正我。在“enlight”项目中,首先编译 java,然后编译 clojure(使用 maven-clojure-plugin)。 clojure 调用 java 函数,但 java 从不调用 clojure。真的吗?但这不是我需要的。我想要 clojure 调用 java java调用 clojure。有没有办法一起编译java和clojure?
    • 你实际上并没有预编译 Clojure 代码——它在运行时加载时被编译。因此,您真正拥有的是一个 Java 应用程序,它包含 clojure.jar 运行时库,因此能够编译和运行代码库的 Clojure 部分。一旦它运行起来,Clojure 就可以调用 Java,反之亦然。
    • true,'一旦运行'。但问题是编译。当您从 java 引用不存在的类(将在运行时生成)时,maven 无法编译项目
    • “不存在的类”是什么意思?通常 Java 不需要知道 Clojure 生成了哪些类,因为它们可以在运行时轻松查找。请参阅我的博客文章中的技术:clojurefun.wordpress.com/2012/12/24/…
    • 我必须承认我通常避免使用 gen-class。这意味着您需要一个额外的编译步骤,使构建复杂化,而且我发现在 Clojure 中编写 Java 类是相当单一的。如果您可以在没有 gen-class 的情况下生活(例如,通过在 Java 本身中编写您需要的 Java 对象),那么您的生活会更简单。我认为可以使 gen-class 与 Java IDE 一起工作,但它本身可能值得一个单独的问题。
    【解决方案2】:

    尽管你的语气是关于 leiningen,但我建议你看看它。 Leiningen 支持 Java 编译,因此在一个项目中结合 java 和 clojure 源代码不是问题。

    逆时针插件,Eclipse 的 clojure 插件,可以与 leiningen 项目文件 (project.clj) 一起使用。因此,在 Eclipse 中,您可以通过在 project.clj 中定义正确的东西来为您处理依赖管理和 java 编译,而无需单独安装 leiningen 或从命令行执行命令。

    在project.clj中设置:java-source-paths,例如:

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

    在包 src/main/java 中放一个类 Foo:

    package main.java;
    
    public class Foo {
        public static final String value = "Michiel";
    }
    

    在 clojure 源文件的某处定义此函数,调用时将打印“Michiel”:

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

    延伸阅读:

    【讨论】:

    • 哦不,我对 lein 没有任何意见。它看起来就像一个手动 CLI 命令,没有与 IDE 正确集成。你是说我可以只安装插件,显示 leiningen 的路径,eclipse 不会显示编译错误?那么maven呢?
    • @piotrek 除了逆时针插件外,您无需安装任何其他东西即可完成这项工作。您必须自己创建一个 project.clj,然后选择“配置 -> 转换为 Leiningen 项目”。
    • @JustinThomas 你说的“相反”是什么意思?
    • 我的意思是Java包括clojure,但我成功了。
    【解决方案3】:

    您也可以尝试框架“Funky”。它将完全分离您的 Clojure 和 Java 代码。看看https://github.com/windler/Funky

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-06-12
      • 1970-01-01
      • 1970-01-01
      • 2019-07-18
      • 2014-03-31
      相关资源
      最近更新 更多