如何直接从Java调用Clojure函数
我有Clojure函数generate-id
。
源代码:
(ns url62.core) ... (defn generate-id [] (int-to-base62 (java.math.BigInteger. (clojure.string/replace (str (java.util.UUID/randomUUID)) "-" "") 16)))
- https://github.com/8protons/url62/blob/master/src/url62/core.clj
我需要从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)
你忘了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 [xy] (+ xy)) (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 lein
或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