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 中符号的顺序,该形式可能编译或不编译。通过调整这个情况,可以得到总是编译但有不同值的表达式。


(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

关于我之前评论的更新 -- 环境中间件参数已经更新,不再依赖于这种行为。我认为我们应该肯定合并这个补丁,这样就没有人再依赖于它。

0

评论者:mpenet

既然这涉及到:or键的评估,这可能值得检查这对http://dev.clojure.org/jira/browse/CLJ-1676是否有影响。

0

评论者:stu

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

0

评论者:jafingerhut

这不是一个现有代码因为无序映射的序列顺序而工作,有时候工作,有时候不工作的情况吗?如果是这样,任何依赖于现有行为的代码可能在Clojure 1.5.1到Clojure 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](https://clojure.atlassian.net/browse/CLJ-1613)(由michalmarczyk报告)
...