请在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映射的seq顺序从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
by

评论者:michaelblume

更新补丁以应用于master

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