【问题标题】:How to invoke Clojure function directly from Java [duplicate]如何直接从Java调用Clojure函数[重复]
【发布时间】:2018-03-08 06:27:15
【问题描述】:

我有 Clojure 函数 generate-id

源代码:

(ns url62.core)
...
(defn generate-id []
  (int-to-base62 (java.math.BigInteger. (clojure.string/replace (str (java.util.UUID/randomUUID)) "-" "") 16)))

我需要从 Java 中执行这个函数。

我尝试过这样的代码:

IFn generateId = Clojure.var("url62.core", "generate-id");
generateId.invoke(UUID.randomUUID());

但这不起作用:

java.lang.IllegalStateException: Attempting to call unbound fn: #'url62.core/generate-id

    at clojure.lang.Var$Unbound.throwArity(Var.java:43)
    at clojure.lang.AFn.invoke(AFn.java:32)
    at clojure.lang.Var.invoke(Var.java:379)

【问题讨论】:

  • 一方面,我同意这个问题与那个问题重复。但是我真的不想将其作为重复项关闭,因为正如@PiotrekBzdyl 所说,该问题的最佳答案不是公认的答案,而是稍后添加的答案。 Alan Thompson 对这个问题也有很好的回答,与 Alex Miller 的链接回答大致相同。

标签: java clojure


【解决方案1】:

你忘了require Clojure 命名空间:

这是项目结构:

-rwxrwxr-x 1 alan alan  162 Sep 26 15:27 compile-run-java.bash*
-rwxrwxr-x 1 alan alan  439 Oct 19  2016 project.clj*
-rw-rw-r-- 1 alan alan  142 Sep 26 16:38 src/embedded_clojure/core.clj
-rw-rw-r-- 1 alan alan  586 Sep 26 15:21 src-java/mypkg/Main.java
-rw-rw-r-- 1 alan alan  125 Oct 19  2016 test/tst/embedded_clojure/core.clj

还有project.clj 文件:

(defproject embedded-clojure "0.1.0-SNAPSHOT"
  :dependencies [
    [org.clojure/clojure "1.8.0"]
  ]
  :java-source-paths ["src-java"]
  :main embedded-clojure.core
  :target-path "target/%s"
  :profiles {:uberjar {:aot :all}})

这是调用嵌入式 Clojure 函数的 Java 类:

package mypkg;
import clojure.java.api.Clojure;
import clojure.lang.IFn;
class Main {
  public static void main( String[] args ) {
    System.out.println( "Java Main.main()" );

    // clojure.core is automatically "required"; you don't need to
    IFn plus = Clojure.var("clojure.core", "+");
    System.out.println( "  plus: " + plus.invoke(1, 2) );

    // any other namespace needs to be "required"
    IFn require = Clojure.var("clojure.core", "require");
    require.invoke(Clojure.read("embedded-clojure.core"));

    IFn add  = Clojure.var("embedded-clojure.core", "add");
    System.out.println( "  add:  " +  add.invoke(2, 3) );
  }
}

Clojure 文件:

(ns embedded-clojure.core
  (:gen-class))

(defn add [x y] (+ x y))

(defn -main [& args]
  (println "Clojure -main:  (add 4 5) =>" (add 4 5)))

Clojure 测试文件:

(ns tst.embedded-clojure.core
  (:use embedded-clojure.core
        clojure.test))

(deftest simple-add
  (is (= 13 (add 6 7))))

运行脚本compile-run-java.bash

#!/bin/bash  -v

lein clean
lein uberjar
# Use Java main()
java -cp /home/alan/demo/embedded-clojure/target/uberjar/embedded-clojure-0.1.0-SNAPSHOT-standalone.jar \
  mypkg.Main

# Use Clojure -main
java -cp /home/alan/demo/embedded-clojure/target/uberjar/embedded-clojure-0.1.0-SNAPSHOT-standalone.jar \
  embedded_clojure/core

现在我们可以从命令行运行了:

 > ./compile-run-java.bash
#!/bin/bash  -v

lein clean
lein uberjar
Compiling 1 source files to /home/alan/demo/embedded-clojure/target/uberjar/classes
Compiling embedded-clojure.core
Created /home/alan/demo/embedded-clojure/target/uberjar/embedded-clojure-0.1.0-SNAPSHOT.jar
Created /home/alan/demo/embedded-clojure/target/uberjar/embedded-clojure-0.1.0-SNAPSHOT-standalone.jar
# Use Java main()
java -cp /home/alan/demo/embedded-clojure/target/uberjar/embedded-clojure-0.1.0-SNAPSHOT-standalone.jar \
  mypkg.Main
Java Main.main()
  plus: 3
  add:  5

# Use Clojure -main
java -cp /home/alan/demo/embedded-clojure/target/uberjar/embedded-clojure-0.1.0-SNAPSHOT-standalone.jar \
  embedded_clojure/core
Clojure -main:  (add 4 5) => 9

我们还可以使用 lein 运行 Clojure -main 或 Clojure 测试:

> lein test
lein test tst.embedded-clojure.core
Ran 1 tests containing 1 assertions.
0 failures, 0 errors.

> lein run
Clojure -main:  (add 4 5) => 9

【讨论】:

  • 谢谢,我忘记了 maven 部分;)我在一个项目包中将 clojoure 源代码与 java 代码(单独的目录)混合为 jar。
  • 我已将我的问题移至新问题:stackoverflow.com/questions/46441626/…
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-11-30
  • 1970-01-01
  • 1970-01-01
  • 2014-04-08
  • 2012-11-24
  • 1970-01-01
相关资源
最近更新 更多