Relrin
Relrin

Reputation: 790

Printing vector as a tree

I'm trying to print in console vector as tree. My vector can contain also any size vectors, its looks like:

["url1" ["ulrA" "urlB" "ulrC"] "url2" ["urlA" ["urlAA" ["urlAAA" "urlAAB"] "urlAB" ["urlABA" ["urlABAA"]]]] ...]

and i want to see something like that:

url1
--urlA
--urlB
--urlC
url2
--urlA
----urlAA
-----urlAAA
-------urlAAB
-----urlAB
-------urlABA
---------urlABAA
...

Code, what I wrote, can't output this example:

(defn print-tree
  ([tree]
    (print-tree tree ""))
  ([tree prefix]
    (apply str prefix (first tree) "\n"
      (map #(print-tree %1 (str prefix "\t")) (rest tree)))))

(defn parse-to-tree [filepath deep]
  (let [urls (read-urls filepath)  ; vector with URLs
        n-threads 25               ; count of parallel threads (change me)
        test-tree ["url1" ["ulrA" "urlB" "ulrC"] "url2" ["urlA" ["urlAA" ["urlAAA" "urlAAB"] "urlAB" ["urlABA" ["urlABAA"]]]]]
        ]              
  ; ... some logic for threads
  (println (print-tree test-tree))
))

As result I'll take big exception in Debian console:

Exception in thread "main" java.lang.IllegalArgumentException: Don't know how to create ISeq from: clojure.lang.Symbol, compiling:(/tmp/form-init8340977500770992520.clj:1:90)
    at clojure.lang.Compiler.load(Compiler.java:7142)
    at clojure.lang.Compiler.loadFile(Compiler.java:7086)
    at clojure.main$load_script.invoke(main.clj:274)
    at clojure.main$init_opt.invoke(main.clj:279)
    at clojure.main$initialize.invoke(main.clj:307)
    at clojure.main$null_opt.invoke(main.clj:342)
    at clojure.main$main.doInvoke(main.clj:420)
    at clojure.lang.RestFn.invoke(RestFn.java:421)
    at clojure.lang.Var.invoke(Var.java:383)
    at clojure.lang.AFn.applyToHelper(AFn.java:156)
    at clojure.lang.Var.applyTo(Var.java:700)
    at clojure.main.main(main.java:37)
Caused by: java.lang.IllegalArgumentException: Don't know how to create ISeq from: clojure.lang.Symbol
    at clojure.lang.RT.seqFrom(RT.java:505)
    at clojure.lang.RT.seq(RT.java:486)
    at clojure.lang.RT.first(RT.java:578)
    at clojure.core$first.invoke(core.clj:55)
    at lab2.core$print_tree.invoke(core.clj:74)
    at lab2.core$print_tree$fn__239.invoke(core.clj:75)
    at clojure.core$map$fn__4245.invoke(core.clj:2559)
    at clojure.lang.LazySeq.sval(LazySeq.java:40)
    at clojure.lang.LazySeq.seq(LazySeq.java:49)
    at clojure.lang.Cons.next(Cons.java:39)
    at clojure.lang.RT.next(RT.java:598)
    at clojure.core$next.invoke(core.clj:64)
    at clojure.core$str$fn__3928.invoke(core.clj:524)
    at clojure.core$str.doInvoke(core.clj:526)
    at clojure.lang.RestFn.applyTo(RestFn.java:139)
    at clojure.core$apply.invoke(core.clj:630)
    at lab2.core$print_tree.invoke(core.clj:75)
    at lab2.core$print_tree$fn__239.invoke(core.clj:75)
    at clojure.core$map$fn__4245.invoke(core.clj:2559)
    at clojure.lang.LazySeq.sval(LazySeq.java:40)
    at clojure.lang.LazySeq.seq(LazySeq.java:49)
    at clojure.lang.Cons.next(Cons.java:39)
    at clojure.lang.RT.next(RT.java:598)
    at clojure.core$next.invoke(core.clj:64)
    at clojure.core$str$fn__3928.invoke(core.clj:524)
    at clojure.core$str.doInvoke(core.clj:526)
    at clojure.lang.RestFn.applyTo(RestFn.java:139)
    at clojure.core$apply.invoke(core.clj:630)
    at lab2.core$print_tree.invoke(core.clj:75)
    at lab2.core$print_tree.invoke(core.clj:72)
    at lab2.core$parse_to_tree.invoke(core.clj:87)
    at lab2.core$_main.doInvoke(core.clj:107)
    at clojure.lang.RestFn.invoke(RestFn.java:421)
    at clojure.lang.Var.invoke(Var.java:383)
    at user$eval5.invoke(form-init8340977500770992520.clj:1)
    at clojure.lang.Compiler.eval(Compiler.java:6703)
    at clojure.lang.Compiler.eval(Compiler.java:6693)
    at clojure.lang.Compiler.load(Compiler.java:7130)
    ... 11 more

How I can fix this trouble?

Upvotes: 0

Views: 373

Answers (1)

xsc
xsc

Reputation: 6073

You have to take care of when to start a new level of indentation, otherwise you'll start to map over leaves (and those are not something that can be mapped over):

(defn print-tree
  ([tree] (apply str (map #(print-tree % "") tree)))
  ([tree prefix]
   (if (vector? tree)
     (->> (map #(print-tree % (str prefix "-")) tree)
          (apply str))
     (str prefix tree "\n"))))

Example:

(println (print-tree '[a [aa ab [aca acb acc] ad] b [ba bb]]))
;; a
;; -aa
;; -ab
;; --aca
;; --acb
;; --acc
;; -ad
;; b
;; -ba
;; -bb

Upvotes: 1

Related Questions