1

I am passing a map generated in Clojure into Java ultimately destined for a JTable. The use of the map function creates a lazy sequence that even with doall, into {} is not realized. Clojure:

(defn test-lz-seq []
  (let [myvec [[1 2  nil][3 4 nil][ 5 6 nil][ 7  8 nil]]
        myvec2 (doall (map #(if (nil? (nth % 2)) (assoc % 2 "NA")) myvec))
        colnames ["VarA" "VarB" "VarC"] ]
    (into {} (java.util.HashMap.
            {":colnames" colnames
             ":data" myvec2} ))))

(println (test-lz-seq))

At the repl looks good:

lnrocks.core>  {:data ([1 2 NA] [3 4 NA] [5 6 NA] [7 8 NA]), :colnames [VarA VarB VarC]}

Java code:

import clojure.java.api.Clojure;
import clojure.lang.IFn;
import clojure.lang.PersistentVector;
.
.
.
public class DialogMainFrame extends JFrame {

    private PersistentVector colnames;
    private PersistentVector data;   
  private  IFn require = Clojure.var("clojure.core", "require");
.
.
.
    System.out.println("==========test code===========");
    System.out.println("");

       IFn testLzSeq = Clojure.var("lnrocks.core", "test-lz-seq");   
      Map<String, PersistentVector> hm = (Map)testLzSeq.invoke();
      System.out.println(hm.get(":data"));
      System.out.println(hm.get(":colnames"));

    System.out.println("");
     System.out.println("===================================");

At the console:

==========test code===========

clojure.lang.LazySeq@e1781
["VarA" "VarB" "VarC"]

===================================

How do I realize the vector in Java?

  • lazy seq is iterable, so the methods for iterable to collection conversion, explained [here](https://www.baeldung.com/java-iterable-to-collection) should work – leetwinski Dec 11 '19 at 12:21
  • 1
    moreover, since it is a also implements java.util.Collection, you should be able to just do `new ArrayList(hm.get(":data"))` to make a realized version. – leetwinski Dec 11 '19 at 12:38
  • @leetwinski new ArrayList(hm.get(":data")) is the solution thanks – Mortimer Cladwell Dec 11 '19 at 12:47
  • 2
    also, `(doall (map ...))` in your code doesn't return vector, even though the collection itself is fully realized. What you need, is to replace `doall` with `vec`, or the whole `(doall (map ...))` with simple `(mapv ...)` – leetwinski Dec 11 '19 at 12:48
  • @leetwinski right again - mapv in clojure without modifications to the Java code does the trick – Mortimer Cladwell Dec 11 '19 at 12:53
  • and more : depending on how are you going to use the returned value, maybe you don't even need any conversion at all: if you don't use random access, just iterating/streaming/looping over the returned seq, it is ok to keep it lazy. It just doesn't have a human friendly `toString` implementation (for obvious reason). – leetwinski Dec 11 '19 at 12:54
  • Here is another discussion with plenty of nuances about LazySeq and how to realize it: https://stackoverflow.com/questions/1641626/how-to-convert-lazy-sequence-to-non-lazy-in-clojure – Sergey Shvets Dec 13 '19 at 23:01
  • `System.out.println` is not Clojure's `prn`. Use `prn` or do your own print by iterating over the collection. – cgrand Dec 17 '19 at 17:00

0 Answers0