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

欢迎!有关如何工作的更多信息,请参阅 关于 页面。

0 投票
集合
Michael Blume 注意到 :or 默认值可能会依赖于其他键的值,见 https://groups.google.com/d/msg/clojure/6kOhpPOpHWM/ITjWwQFS_VQJ

Michael 的 Gist https://gist.github.com/MichaelBlume/4891dafdd31f0dcbc727 展现了一个关联 :keys 和 :or,编译与否取决于 :keys 中符号顺序的情况。通过调整此情况,可以到达总是编译但不产生相同值的情况


(let [foo 1
       bar 2
       {:keys [bar foo]
        :or {foo 3 bar (inc foo)}} {}]
  {:foo foo :bar bar})
;= {:foo 3, :bar 4}

(let [foo 1
      bar 2
      {:keys [foo bar]
       :or {foo 3 bar (inc foo)}} {}]
  {:foo foo :bar bar})
;


我相信最自然的解决方案是要求在包围作用域中评估 :or 默认值,其中不包含任何用解构引入的局部变量。这种方法由0001补丁采用。

10 个答案

0 投票

评论由:michaelblume 提供

我怀疑这是正确的事情要做,但我认为重要的是要注意这将破坏现有的代码 https://github.com/ngrunwald/ring-middleware-format/blob/master/src/ring/middleware/format_params.clj#L214

0 投票

评论由:michaelblume 提供

关于我之前的评论的更新 -- 环境中间件参数已更新,因此不再依赖于这种行为。我认为我们肯定应该合并此补丁,以免其他人依赖。

0 投票

评论由:mpenet 创建

由于这涉及到:or键的评估,可能需要检查这一点是否会对http://dev.clojure.org/jira/browse/CLJ-1676造成影响。

0 投票

评论由:stu 创建

这是一个行为变化,文档并没有保证这种行为,现有的代码可能依赖于当前的行为。

0 投票

评论由:jafingerhut 创建

这不是一种情况吗?即现有代码由于无序映射的序列顺序的巧合而工作?如果是这样,任何依赖于现有行为的代码有时会破坏,有时不会破坏,当Clojure的映射序列顺序从Clojure 1.5.1更改为Clojure 1.6.0,然后再从1.6.0更改为1.7.0时。

0 投票

评论由:michaelblume 提供

是的,确实如此,我因为那些变化看到现有代码崩溃,因此有关于这个工票的讨论。

0 投票

评论由:michaelblume 提供

更新此补丁

0 投票
by
评论者:michalmarczyk

@Stuart

以下是相同代码片段在 Clojure 1.6 REPL 和 Clojure 1.7 REPL 中的评估结果,两个 REPL 都是新启动的,结果不同


Clojure 1.6.0
(let [foo 1 bar 2
      {:keys [foo bar]
       :or {foo 3 bar (inc foo)}} {}]
  [foo bar])
[3 2]

Clojure 1.7.0
(let [foo 1 bar 2
      {:keys [foo bar]
       :or {foo 3 bar (inc foo)}} {}]
  [foo bar])
[3 4]


虽然文档中并没有保证 {{:or}} 与 {{:keys}} 之间不会有令人惊讶的交互,但如上所示,任何依赖 1.6 行为的现有代码在 1.7 中已经被破坏。指定并坚持某种行为将防止未来出现此类惊喜。

我还认为,当前的行为在某种意义上是“随机的”,因为没有原则性的原因可以解释为什么会有这样的期望——因此我提出了将 {{:or}} 默认值指向包围作用域的提案,这是我已在补丁中实现的。
0 投票
by

评论由:michaelblume 提供

已更新补丁以应用 master

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