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的map序列顺序从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 报告)
...