在 Clojure 中使用 repl 而不是 println

Posted

技术标签:

【中文标题】在 Clojure 中使用 repl 而不是 println【英文标题】:Use repl instead of println in Clojure 【发布时间】:2022-01-11 09:22:37 【问题描述】:

假设我们需要评估源文件中的多个子句,例如

test.clj

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

如果我们直接使用cljlein repl,则只会显示最后的评估,

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

我们可以用println包围它们以显示所有它们,

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

有什么更好的替代方法可以避免在源代码中侵入printlns,同时能够打印出 REPL 保护下的所有预期评估?

@Solution

感谢@Sean Corfield 的回答中的tap>,我们可以得到如下期望的结果,

将每个想要打印的人发送到tap>

test-with-tap.clj

(-> @(def x 1) tap>)
(-> @(def y 2) tap>)
(-> @(def z 3) tap>)
tap>add-tap 开启之前,REPL 将不会收到任何输出。
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

【问题讨论】:

【参考方案1】:

我还没有机会玩tap>。这些年来我最喜欢的是spy 函数系列in the Tupelo library。具体来说,请查看spyxspyx-pretty 和let-spy。

【讨论】:

艾伦,非常感谢您维护良好的精彩项目。我一定会把它添加到工具包中。【参考方案2】:

tap> 可能是您正在寻找的东西 - https://clojuredocs.org/clojure.core/tap%3E - 这使您可以将完整的 Clojure 值(不仅仅是字符串)发送到注册为侦听器的任何函数,例如 Portal 之类的东西 - @987654322 @ - 这是我每天都在使用的东西,但您也可以在add-tap 中使用像println 这样简单的东西来显示每个tap> 的值。

tap> 调用可以保留在您的代码中,即使在生产中也是如此,因为使用它们几乎没有开销。

虽然tap> 返回一个布尔值,但您可以使用(doto expr tap>) 评估并返回expr,但仍将值发送给任何点击侦听器。 tap> 是一个很棒的调试工具。

【讨论】:

非常感谢,肖恩。 tap> 提供的东西比我一开始想象的还要好。

以上是关于在 Clojure 中使用 repl 而不是 println的主要内容,如果未能解决你的问题,请参考以下文章

Clojure 的 Emacs/Swank/Paredit 教程

Clojure 1.8的套接字repl和nREPL之间的具体区别是什么?

Clojure:使用来自 REPL 的库函数

Clojure 的加载字符串在 repl 中有效,但在 `lein run` 中无效

Clojure - 在没有project.clj的情况下启动REPL

无法在spacemacs cider(Clojure)中切换到repl