2024 年 Clojure 状态调查! 分享您的想法。

欢迎!有关此功能的更多信息,请参阅 关于 页面。

+5
打印

因为 clojure.core/pr-str 使用 with-out-str 捕获 pr 的输出(而 pr 无法被解析为可写的事物 - 只使用 out)。

如果您对某些惰性结果进行 pr-str,您可以使用 println 在输出中穿插副作用。例如,在我的情况下,我正在从库 criterium 提取基准,并尝试将数据结构打印到文件。解决方案是提供一个接受写入器的 pr/pr-str 重载。我注意到 pr-on 提供了一些功能,但它不是公开的。

这是一个在将程序输出持久化为 EDN 时令人烦恼的错误,因为随机穿插的 stdout 消息使其对 read-string 无效。我们不应需要我们的函数必须是纯的才能使 pr-str 如期工作。

我省略了一个修补程序,因为虽然我认为修复很简单,但我不确定它应该放在哪里(例如,使 pr-on 公开,更改 pr,更改 pr-str)。

5 个答案

0

评论者:stu

作为一个变通方法,使用 print-dup 或 print-method

0

评论者:ocal

因此,我认为针对此问题的解决方案是修改(链接:https://github.com/clojure/clojure/blob/841fa60b41bc74367fb16ec65d025ea5bde7a617/src/clj/clojure/core.clj#L4702-L4709 文本:pr-str)以使用(链接:https://github.com/clojure/clojure/blob/841fa60b41bc74367fb16ec65d025ea5bde7a617/src/clj/clojure/core.clj#L3660-L3667 文本:pr-on)及其自己的字符串写器。这样,所有指向输出的内容仍将到达目的地,用户可以在真正需要时将其包裹在 with-out-str 中。

我想不出为什么有人会依赖这种功能,但存在这种风险,这可能会(链接:https://xkcd.com/1172/ 文本:中断某人的工作流程)。我建议(如果没有充分的理由不提交补丁,我将提交一个补丁),我们将 pr-str 修改为直接使用 pr-on 与字符串写器进行交互而不是默认的 pr,即 out。这意味着 pr-str 将不得不重新实现 var args 处理,但我认为这没问题。

主要原因在于 prepl 使用 pr-str 对数据进行编码,以便通过套接字发送。这意味着我的(链接:https://github.com/Olical/conjure 文本:prepl 工具)将捕获所有 lazy-seq 结果,因为 pr-str 位于上游。对此的另一个解决方案是配置预置的 not 使用 pr-str 但我的函数,但我觉得这是回避问题。

我认为正确的做法是修复 pr-str,我认为其行为既不正确也不符合预期,将来会迷惑更多的人。再次,我很乐意尝试修复这个问题,但我想先听听您的意见。

0

评论者:ocal

我突然意识到 p...-str 所有函数都有这个问题,目前正在思考如何为所有这些函数解决问题。因此,任何打印出 lazy-seq 的输出都不会发送到 out。也许我可以将其拆分,这样它就不会被发送到 out,而是发送到其他可以单独重新绑定的地方,而不使用 with-out-str。

0

评论者:ocal

那么,对于传递给 p...-str 函数的任何 lazy-seq 上的 doall 呢?它们无论如何都需要完全解析,这样我们可以在它们被包裹在 with-out-str 中之前解析它们。我认为这意味着内部打印函数可以保持不变,而 -str 变体可以确保在打印之前解析这些序列。我认为这不会太多改变函数的特性,但会解决所有这些问题。

至少,用户可以(pr-str (doall my-seq))来确保在 pr-str 中的 with-out-str 调用之外解析出所有懒加载。这可以用作临时解决方案。

意见如何?

0
参考: https://clojure.atlassian.net/browse/CLJ-1532(由 alex+import 报告)
...