Search code examples
clojureread-eval-print-loopleiningen

Use repl instead of println in Clojure


Let's say we need evaluate a number of clauses in a source file, e.g.

test.clj

@(def x 1)
@(def y 2)
@(def z 3)

Only the last evaluation shows up if we plainly use either clj or lein repl,

user => (load-file "test.clj")
3 

We can surround each of them by println to show all of them,

test-with-println.clj

(println @(def x 1))
(println @(def y 2))
(println @(def z 3))
user => (load-file "test-with-println.clj")
1
2
3
nil

What are the better alternatives to avoid invasive printlns all over the source code while able to print out all the intended evaluations under the umbrella of REPLs?

@Solution

Thanks to tap> from the answer @Sean Corfield we can have desired results as follows,

  • pipe every wannabe printed out to tap>.

test-with-tap.clj

(-> @(def x 1) tap>)
(-> @(def y 2) tap>)
(-> @(def z 3) tap>)
  • REPLs will receive none of their outputs until tap> is turned on by add-tap.
user=> (load-file "test-with-tap.clj")
nil
user=> (add-tap @(def out (bound-fn* println)))
nil
user=> (load-file "test-with-tap.clj")
1
2
3
user=> (remove-tap out)
nil
user=> (load-file "test-with-tap.clj")
nil

Solution

  • tap> is probably what you're looking for - https://clojuredocs.org/clojure.core/tap%3E - This lets you send full Clojure values (not just strings) to any function registered as a listener, which can be something like Portal for example - https://github.com/djblue/portal - which is something I use all-day, every-day, but you can also use something as simple as println in add-tap to get every tap>'d value displayed.

    The tap> calls can stay in your code, even in production, since there is next to no overhead to using them.

    Although tap> returns a Boolean, you can use (doto expr tap>) to evaluate and return expr but still send the value to any tap listeners. tap> is a great debugging tool.