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

欢迎!请参阅 关于 页面以获取更多关于它是如何工作的信息。

0 投票
Clojure

集合类通过委托给 {{RT.printString}} 实现 {{toString}},而转而影响 * }}

Clojure 1.9.0-beta1 user=> (binding [*print-readably* false] (str ["foo"])) "[foo]" user=> (binding [*print-readably* true] (str ["foo"])) "[\"foo\"]"

附带的补丁通过将集合 {{toString}} 实现中调用 {{RT.printString}} 替换为新方法 {{RT.prString}},该方法明确绑定 * }}

请参阅 https://groups.google.com/d/msg/clojure/S13swxLy1ng/FKLYdY9HAgAJ 的原始报告,其中描述了由上述问题引起的 {{lazy-seq}}、{{print}} 和 {{str}} 之间的相互作用。

7 答案

0 投票

评论由:alexmiller

我不清楚当前的这种行为是否正确,也不清楚它是如何工作的。

0 投票
_评论由:michalmarczyk_

我预计当应用于不可变项的持久集合时,{{str}} / {{toString}} 应该是稳定的。换句话说,当我应用不可变输入时,我期望它仅仅是一个显式传入的参数的纯函数。

这里用户实在没有任何方式可以预期依赖任何动态变量,或者实际上任何其他东西,只有参数 - 这是一个纯值。

原始例子在 Google 群组线程中是一个惰性序列,本质上是一个值 - (lazy-seq [(str ["a string"])]) - 该值根据是否在创建它和对其调用 {{pr-str}} 之间传递给 {{print}} 而返回不同的 {{pr-str}}(和 {{print-method}})表示。


Clojure 1.9.0-beta1
用户=> (let [x (lazy-seq [(str ["a string"])])] (print x) (pr-str x))
("[a string]")("(\"[a string]\")")
用户=> (let [x (lazy-seq [(str ["a string"])])] (pr-str x))
"(\"[\\\"a string\\\"]\")"


在这里,用户可能会期望{{pr-str}}的调用独立于{{print}}的调用,因为前者只有在其后返回后才执行,但实际上却存在一种神秘的交互。

这次补丁解决了这个问题


Clojure 1.9.0-master-SNAPSHOT
用户=> (let [x (lazy-seq [(str ["a string"])])] (print x) (pr-str x))
(["a string"])("(\"[\\\"a string\\\"]\")")
用户=> (let [x (lazy-seq [(str ["a string"])])] (pr-str x))
"(\"[\\\"a string\\\"]\")"
0 投票

评论由:alexmiller

这或许是一个哲学上的争论,我并没有确切的答案,但乐于来回讨论。 :)

同意持久不可变值集合是一个价值。然而,有许多方式可以构建表示该不可变数据视图的字符串 - 我们在Clojure打印系统中内置了几个(pprint、pr、print)+ 一系列可调的旋钮,如集合大小限制等。我看不出任何原则会导致我认为toString必须独立于选择该视图的旋钮。

换句话说,我并不一定认为这是一个需要解决的问题。

0 投票

评论者:notespin

我认为这确实是有点哲学的。然而,为了给出一些支持补丁的重量,我认为toString以及thus str通常被视为程序员期望稳定的。所以我会说当前的行为打破了最小惊奇原则。我会投票支持使str/toString稳定,但说了这些,这种变化很小有可能会成为对某个人的破坏性变化。

0 投票

评论由:alexmiller

作为一名经验丰富的Java老兵,我对toString没有任何期望。通常在Java中,它们基于可变字段构建,且非常不稳定,所以我当然没有分享你的期望。 :)

str本质上涉及“打印”(创建值的字符串视图)。我认为str是“稳定的”,但不仅仅是其显式输入的函数(boo隐藏状态)。为了做一个类比,有许多方式可以从日期对象创建字符串,java.util.Date的toString将使用您的时间区进行格式化,这是一个外部隐藏状态。

我仍然不一定反对这里的更改。我只是觉得这不是显然正确的事情要做的。

从一般的角度来看,我认为“最小惊奇原则”意味着人们找到惊奇的东西比实际上存在的要大得多,所以我对此很少看重。我更看重一些从某些声明原则中推导出来的论点。我认为这个领域未充分记录/未充分指定。

0 投票
by

评论由:pbwolf发表

原始问题从{{toString}}开始。一个更直观的问题是,这个问题演示了{{pr}}在发出EDN时是不可靠的。

中间是否存在{{print-str}}(调用者可能与此无关)对结果有重大影响

`
user> (clojure.edn/read-string

    (first
      (clojure.edn/read-string
        (let [mk-str (fn [] (lazy-seq [(str ["ZiZi"])]))
              a (mk-str)]
          ;(print-str a)
          (pr-str a)))))

["ZiZi"]

user> (clojure.edn/read-string

    (first
      (clojure.edn/read-string
        (let [mk-str (fn [] (lazy-seq [(str ["ZiZi"])]))
              a (mk-str)]
          (print-str a)
          (pr-str a)))))

[ZiZi]
`

0 投票
by
参考:https://clojure.atlassian.net/browse/CLJ-2248(由michalmarczyk报告)
...