如何保持数组映射中的顺序?长度超过 8 的数组映射在 Clojure 和 Clojurescript 中的行为完全不同。示例:
cljs
(array-map :a true :c true :d false :b true :z false :h false
:o true :p true :w false :r true :t false :g false)
-> {:o true, :p true, :r true, :t false, :w false, :z false, :a true, :b true, :c true, :d false, :g false, :h false}
clj
(array-map :a true :c true :d false :b true :z false :h false
:o true :p true :w false :r true :t false :g false)
-> {:a true :c true :d false :b true :z false :h false :o true :p true :w false :r true :t false :g false}
最佳答案
更新:
从版本 2371 开始,对 cljs.core/array-map 的非高阶调用由宏支持,该宏为 > 8 个键值对发出 HashMap 。请参阅CLJS-873门票 + 补丁。
(原始答案如下。)
最可能的解释是您在 REPL 上执行此操作。 ClojureScript 的标准 REPL 在 (Clojure) 命名空间 cljs.repl
中实现,通过从 JS 环境接收返回值的字符串表示形式、读取它们以生成 Clojure 数据并再次将它们打印出来来进行操作。请参阅line 156 of src/clj/cljs/repl.clj在 ClojureScript 的源代码中(链接到版本 2371)。
当在 REPL 上输入的表达式的返回值是大型数组映射 – 或排序映射,或 data.avl 时排序映射 - 读取其字符串表示形式将在 Clojure 端生成一个 HashMap 。不用说,当打印这个 HashMap 时,原始顺序就会丢失。
要确认这是否确实发生了,请尝试在 REPL 中执行此操作(从当前结帐中的 ClojureScript REPL session 复制并粘贴):
ClojureScript:cljs.user> (array-map 1 2 3 4 5 6 7 8 9 10 11 12 13 14)
{1 2, 3 4, 5 6, 7 8, 9 10, 11 12, 13 14}
ClojureScript:cljs.user> (array-map 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18)
{7 8, 1 2, 15 16, 13 14, 17 18, 3 4, 11 12, 9 10, 5 6}
ClojureScript:cljs.user> (seq (array-map 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18))
([1 2] [3 4] [5 6] [7 8] [9 10] [11 12] [13 14] [15 16] [17 18])
ClojureScript:cljs.user> (hash-map 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18)
{7 8, 1 2, 15 16, 13 14, 17 18, 3 4, 11 12, 9 10, 5 6}
请注意,在数组映射上调用 seq
确实会产生预期的结果。
关于Clojurescript 数组映射顺序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26349324/