Search code examples
javaclojureclojure-java-interop

How to both declare a Clojure function and immediately run from Java code using the clojure-utils?


I want to declare a Clojure function and instantly evaluate it in the Java code using clojure-utils. How to do this?

The code I'm using is this:

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);
}

If I just use the following expression in the string variable s, it will work fine:

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

And the Java Compiler will show:

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

But if I try to both declare my function and then try to call it from the code, like this:

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

The Compiler will only show this:

Evaluating Clojure code:

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

UPDATE: I wrote this construction, it's awful, but it works:

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

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

      (list* (fun lst))) 

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

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

UPDATE 2 (Fixed):

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

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

Solution

  • It is not a REPL, so it will only read one s-expression and evaluate it. You should eval every one.

    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;
    }