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
      }
      {: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

这不是一种情况吗?如果现有代码能工作,那是由于无序映射的seq顺序偶然工作的?如果是这样,依赖当前行为的任何代码,在Clojure对映射的seq顺序从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中 evaluates the same code snippet,然后在Clojure 1.7 REPL中再次evaluate,两个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报告)
...