beginners

Noah McMillan 2025-10-20T12:02:24.235749Z

Does anyone know of any good ways to visualise codebase as a call graph?

2025-10-20T13:00:13.858799Z

There seams to be https://github.com/skinkade/clj-auto-call-graph. I'm pretty sure there was something more sophisticated but I can't remember and couldn't find it. I also created https://github.com/jpmonettas/clindex which indexes entire Clojure and ClojureScript codebases whith all dependencies into Datascript (basically a graph), so you can query what you need or navigate the graph with the api although there is nothing there to automatically generate a graph visualization. There is also https://github.com/jpmonettas/clograms to help you create graph visualizations from your code base. It is like a diagrams editor that knows about your codebase deps, functions, namespaces, etc

👍 1
p-himik 2025-10-20T13:01:32.582939Z

A previous question like that with some answers in its thread: https://clojurians.slack.com/archives/C03S1KBA2/p1749199747045169

👍 1
Jim Newton 2025-10-20T15:51:40.831479Z

does anyone see a reason my error message is not being printed like I expect? It's printing as clojure.lang.LazySeq@... rather than as the values in the lazy list.

(defmacro weighted-case 
  "E.g., (weighted-case 50 :a
                        20 :b
                        30 :c)
    Randonmly one of the clauses and evaluate its body.
    The random selection is biased so that each clause is selected
    with the given probability.  In this example :a is selected 50%
    of the time, :b 20% of the time, and :c 30% of the time.
    "
  [& args]
  (assert (even? (count args)))
  (let [pairs (partition 2 args)
        percent (reduce + 0 (map first pairs))
        args (mapcat (fn [[p body]]
                       [p `(fn [] ~body)])
                     pairs)]
    (assert (= 100 percent)
            (format "does not sum to 100: %s" (doall (map first pairs))))    
    `(weighted-case-impl ~@args)))

seancorfield 2025-10-20T15:57:07.005749Z

That's how lazy sequences print by default. doall realizes the sequence but it is still a lazy sequence.

👍🏻 1
Jim Newton 2025-10-20T15:57:52.034299Z

hmm, how can it be lazy and also realized?

ghadi 2025-10-20T15:58:14.678019Z

format is coercing a seq to a string via Object.toString()

ghadi 2025-10-20T15:59:00.390289Z

control the conversion directly: (format "....%s" (pr-str (map ...)))

ghadi 2025-10-20T16:00:07.179819Z

via the print system ( pr-str and friends)

Jim Newton 2025-10-20T16:00:11.319629Z

@ghadi, got it. thanks.

seancorfield 2025-10-20T16:00:30.005089Z

user=> (type (map inc [1 2 3 4]))
clojure.lang.LazySeq
user=> (type (doall (map inc [1 2 3 4])))
clojure.lang.LazySeq
A realized lazy sequence is still a lazy sequence, by type.

seancorfield 2025-10-20T16:01:50.239549Z

Expanding on that:

user=> (type (seq (map inc [1 2 3 4])))
clojure.lang.ChunkedCons
user=> (str (map inc [1 2 3 4]))
"clojure.lang.LazySeq@f0c03"
user=> (str (doall (map inc [1 2 3 4])))
"clojure.lang.LazySeq@f0c03"
user=> (str (seq (map inc [1 2 3 4])))
"(2 3 4 5)"

seancorfield 2025-10-20T16:03:48.815139Z

And as Ghadi noted:

user=> (pr-str (map inc [1 2 3 4]))
"(2 3 4 5)"
user=> (pr-str (doall (map inc [1 2 3 4])))
"(2 3 4 5)"
user=> (pr-str (seq (map inc [1 2 3 4])))
"(2 3 4 5)"

2025-10-20T17:23:50.600439Z

> hmm, how can it be lazy and also realized? you already had that, the way it prints isn't caused by being unrealized, it prints that way to avoid realizing lazy seqs unnecessarily