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})
;= {: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

这不是一种现有代码基于无序映射的 seq 排序偶然工作的场景吗?如果是这样,当 Clojure 在 1.5.1 到 1.6.0 以及 1.6.0 到 1.7.0 版本之间的映射 seq 排序发生变化时,任何依赖现有行为的代码有时会断裂,有时不会断裂。

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报告)
...