如何直接从Java调用Clojure函数

时间:2017-09-26 21:59:04

标签: 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)))

我需要从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)

1 个答案:

答案 0 :(得分:5)

您忘记了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