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

欢迎!有关该机制的工作方式,请参阅 关于 页面获取更多信息。

0
Collections
Michael Blume 注意到 :or 默认值可以依赖于其他键的值,请参阅 https://groups.google.com/d/msg/clojure/6kOhpPOpHWM/ITjWwQFS_VQJ

Michael 的 Gist https://gist.github.com/MichaelBlume/4891dafdd31f0dcbc727 展示了一个涉及 :keys 和 :or 的关联形式,其编译是否成功取决于 :keys 中符号的顺序。通过对该示例进行调整,可以得到始终编译,但根据 :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})
;= {:foo 3, :bar 2}


我相信最好的解决方案是要求在不存在任何解构局部变量的外部作用域中评估 :or 默认值。这种做法被 0001 补丁采用。

10 个答案

0

评论者:michaelblume

我认为这是正确的事情,但我觉得很重要地指出,这将破坏现有的代码 https://github.com/ngrunwald/ring-middleware-format/blob/master/src/ring/middleware/format_params.clj#L214

0

评论者:michaelblume

关于我之前评论的更新 -- ring-middleware-params 已经更新,不再依赖这种行为。我认为我们应该毫不犹豫地合并这个补丁,这样就不会有人再依赖于它。

0

评论由 mpenet 提出

由于这涉及到 :or 键的评估,因此检查这是否可能对 http://dev.clojure.org/jira/browse/CLJ-1676 也有所影响可能是有价值的。

0

评论由 stu 提出

这是一个行为改变,文档并未承诺请求的行为,并且现有的代码可能依赖于当前的行为。

0

评论由 jafingerhut 提出

这难道不是一个现有代码偶然地由于无序映射的顺序而正常工作的例子吗?如果是的话,任何依赖于现有行为的代码,当 Clojure 映射的顺序从 1.5.1 版本到 1.6.0 版本,再从 1.6.0 版本到 1.7.0 版本改变时,有时会破裂,有时不会破裂。

0

评论者:michaelblume

是的,它确实如此,我也看到由于这些变化导致现有代码破裂的情况,因此引发了这次讨论。

0

评论者:michaelblume

更新此补丁

0
_评论由 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
通过

评论者:michaelblume

已更新修订版以适用于master

0
通过
参考:[链接](https://clojure.atlassian.net/browse/CLJ-1613)(由michalmarczyk报告)
...