如何直接从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