如何在 Clojure REPL 导入本地 Java class?

How to import local Java class at Clojure REPL?

类似问题已有答案,但他们倾向于使用 Maven,这不适合我的项目。此外,我还没有找到任何具体示例来说明您用于在 repl 中导入的语法,尤其是当 class 是本地的而不是来自网络时。

我想将 Java class 导入到我的 Clojure 项目中:

public class MyLocalClass1 {
    int x;
    String y;

    public MyLocalClass1() {
        this.x = 0;
        this.y = "hello there";
    }

    public MyLocalClass1(int x, String y) {
        this.x = x;
        this.y = y;
    }

    public void setX(int x) {
        this.x = x;
    }

    public void setY(String y) {
        this.y = y;
    }

    public int getX() {
        return x;
    }

    public String getY() {
        return y;
    }
}

我在 Idea 中成功构建为 Java2Import.jar。

这里是 project.clj,我导入 jar 的地方:

  :description "FIXME: write description"
  :url "http://example.com/FIXME"
  :license {:name "EPL-2.0 OR GPL-2.0-or-later WITH Classpath-exception-2.0"
            :url "https://www.eclipse.org/legal/epl-2.0/"}
  :dependencies [[org.clojure/clojure "1.10.1"]]
  :resource-paths ["/path/to/my/Java/project/Java2Import/artifacts/Java2Import/"]
  :repl-options {:init-ns import-local-java-4.core})

但是,当我尝试导入时,出现错误:

import-local-java-4.core=> (import (Java2Import.Java2Import))
Syntax error macroexpanding clojure.core/import at (/tmp/form-init9909516591129619328.clj:1:1).
Java2Import.Java2Import - failed: #{(quote quote)} at: [:class :quoted-spec :quote] spec: :clojure.core.specs.alpha/quotable-import-list
() - failed: Insufficient input at: [:package-list :spec :classes] spec: :clojure.core.specs.alpha/package-list
Java2Import.Java2Import - failed: #{(quote quote)} at: [:package-list :quoted-spec :quote] spec: :clojure.core.specs.alpha/quotable-import-list
(Java2Import.Java2Import) - failed: simple-symbol? at: [:class :spec] spec: :clojure.core.specs.alpha/quotable-import-list

我做错了什么?

克隆此 repo 并查看目录结构以及 project.clj

源代码文件如下所示:


~/io-tupelo/clj-java-template > ls -1 **/*.{clj,java}
 project.clj
 src/clj/demo/core.clj
 src/java/demo/Calc.java
 test/clj/_bootstrap.clj
 test/clj/tst/demo/core.clj

测试命名空间显示正确的语法:

(ns tst.demo.core
  (:use demo.core tupelo.core tupelo.test)
  (:require
    [tupelo.string :as str])
  (:import [demo Calc]))

(dotest
  (is= 5 (add2 2 3))            ; from src/clj/demo/core.clj
  (is= 42 (Calc/add2 29 13))    ; from src/java/demo/Calc.java
  )

运行 中的单元测试 test/clj/tst/demo/core.clj:


~/io-tupelo/clj-java-template > lein clean ; lein test
Compiling 1 source files to /Users/alanthompson/io-tupelo/clj-java-template/target/default+test+test/class-files

lein test _bootstrap

-----------------------------------
   Clojure 1.10.3    Java 17.0.2
-----------------------------------

lein test tst.demo.core

Ran 2 tests containing 2 assertions.
0 failures, 0 errors.

您不需要将 Java 代码编译成 JAR 文件。从表面上看,如果只使用 Java 个源文件就容易多了。

你也可以在REPL中运行:


~/io-tupelo/clj-java-template > lein repl
Compiling 1 source files to /Users/alanthompson/io-tupelo/clj-java-template/target/default/class-files

demo.core=> (import '[demo Calc])
demo.Calc
demo.core=> (prn :result (Calc/add2 6 7))
:result 13
nil

请注意 requireimport 的函数调用语法在 REPL 中与 (ns ...) 的宏语法不同表格![=2​​3=]

此外,对您的 Java 代码所做的任何编辑都不会在 REPL 中得到体现。您将需要退出并重新启动 REPL 以强制 Java 重新编译。


P.S.

正如 README 所解释的,我发现使用 lein-test-refresh 插件更好。恕我直言,它就像是类固醇的 REPL!

P.P.S.

如果你只有一个 JAR 文件(即没有 Java 源代码),你可能希望使用 lein install 命令,它将 JAR 文件复制到本地 Maven 缓存中 ~/.m2 在哪里 Leiningen 可以正常找到它。