【问题标题】:How to both declare a Clojure function and immediately run from Java code using the clojure-utils?如何声明一个 Clojure 函数并立即使用 clojure-utils 从 Java 代码运行?
【发布时间】:2023-04-11 00:50:01
【问题描述】:

我想声明一个 Clojure 函数并使用 clojure-utils 在 Java 代码中立即对其进行评估。如何做到这一点?

我使用的代码是这样的:

public static void main(String[] args) {

    String s = "(defn fun[lst] (map #(/ % 2) lst))" +
               "(list* (#'clojure.core/fun '(1 2 3 4 5)))";
    System.out.println("Evaluating Clojure code: " + s);
    Object result = mikera.cljutils.Clojure.eval(s);
    System.out.println("=> " + result);
}

如果我只是在字符串变量s 中使用以下表达式,它会正常工作:

(list* (map #(/ % 2) '(1 2 3 4 5)))

Java 编译器会显示:

=> (1/2 1 3/2 2 5/2)

但如果我尝试同时声明我的函数,然后尝试从代码中调用它,如下所示:

String s = "(defn fun[lst] (map #(/ % 2) lst))" 
         + "(list* (fun '(1 2 3 4 5)))";

编译器只会显示这个:

Evaluating Clojure code:

(defn fun[lst] (map #(/ % 2) lst))(list* (#'clojure.core/fun '(1 2 3 4 5)))
=> #'clojure.core/fun

更新: 我写了这个结构,很糟糕,但它有效:

String s = 
"(do 
    (defn main[lst]

      (defn fun[lst]
        (map #(/ % 2) lst))

      (list* (fun lst))) 

    (main '(1 2 3 4 5)))"

结果: => (1/2 1 3/2 2 5/2)

更新 2(固定):

(do 
    (defn fun[lst]
        (map #(/ % 2) lst))

    (list* (fun '(1 2 3 4 5))))

【问题讨论】:

  • 是的,这里有一个表达式,所以它可以工作...您不需要主表达式。每次执行主函数时都会定义函数...:D

标签: java clojure clojure-java-interop


【解决方案1】:

它不是一个 REPL,所以它只会读取一个 s 表达式并对其进行评估。你应该评估每一个。

public static void main(String[] args) {
    clojure("(defn fun[lst] (map #(/ % 2) lst))");
    clojure("(list* (#'clojure.core/fun '(1 2 3 4 5)))");
}

public static Object clojure(String s) {
    System.out.println("Evaluating Clojure code: " + s);
    Object result = mikera.cljutils.Clojure.eval(s);
    System.out.println("=> " + result);
    return result;
}

【讨论】:

  • 感谢您的回答。我发现也可以将其作为一个表达式来执行。我更新了我的帖子以显示如何。也许这个解决方案看起来不太好看或不太优雅,但至少它可以满足我的需求。
  • 但是在 Java 中调用 Clojure 代码的最佳方式是什么?你能展示如何从 Java 调用一些 Clojure 脚本吗?是否可以在 Java 项目树中包含 .clj 脚本文件?
【解决方案2】:

您只是在使用字符串评估。但是直接使用与 Clojure 的互操作更为明显。

例如你可以使用加载字符串函数:

IFn loadString = Clojure.var("clojure.core", "load-string");
Object result = loadString.invoke("(println \"Appel\")(your clojure code)");

关于互操作性:http://clojure.github.io/clojure/javadoc/

【讨论】:

  • 我改它是因为它已经过时了
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-05-07
  • 1970-01-01
相关资源
最近更新 更多