gpt4 book ai didi

map - Clojure Maps,键值创建顺序

转载 作者:行者123 更新时间:2023-12-05 01:07:32 29 4
gpt4 key购买 nike

clojure profiling library ,有一个原子存储一些分析信息,它被许多函数修改。在评论中,他们断言汇总统计信息(其中一个函数)是出于效率目的最后调用的,但我看不出在实际代码中是如何执行的。

然后我注意到可以强制执行的一种方式是构建 map 的顺序,因此我重新创建了一个更简单的示例来演示。

(defn t []
(let [a (atom {})]
{:b (swap! a #(assoc % :data 'is-here))
:c (keys @a)}))

在这里,与注释一致,代码中首先出现的 :b 或 :c 将确定 a 的值。当然必须有一些排序,但这种行为是否有保证?似乎不应该,因为无序散列没有排序,这可能对并行性产生不利影响。

最佳答案

我会将 map 文字的评估顺序视为实现细节,并在 map 文字中使用具有副作用(例如设置原子状态)的非常量表达式来自找麻烦。

对于定义明确的评估语义,请使用函数调用,其中保证从左到右评估参数。

(let [i (atom 0)] 
(hash-map :a (swap! i inc) :b (swap! i inc) :c (swap! i inc)))
;=> {:a 1, :c 3, :b 2}

请注意,由于我们使用了哈希映射,因此键是乱序的,但值与写入顺序中的键相对应。

实现细则

map 文字(1.5 版)的实现细节取决于以下几点:
  • 读者将未评估的映射文字视为小映射(8 对或更少)的有序数组映射或较大映射的无序哈希映射。
  • 如果键和值是常量表达式,编译器评估器将读取器提供的映射表达式解析为无序哈希映射,而不管大小,但会将其评估为数组映射。否则,编译器-评估器会根据读取器提供的键顺序进行评估,具体取决于大小。

  • 一个小例子会让这个更清楚一点(也许):
    user=> {:a 1, :b 2, :c 3}
    {:a 1, :c 3, :b 2}
    user=> (type *1)
    clojure.lang.PersistentArrayMap

    user=> (def m1 {:a 1, :b 2, :c 3})
    #'user/m1
    user=> m1
    {:a 1, :c 3, :b 2}
    user=> (type m1)
    clojure.lang.PersistentHashMap
    user=> (eval m1)
    {:a 1, :c 3, :b 2}
    user=> (type *1)
    clojure.lang.PersistentArrayMap

    但...
    user=> (def m2 {:a ((fn [] 1)), :b 2, :c 3})
    #'user/m2
    user=> m2
    {:a 1, :b 2, :c 3}
    user=> (type m2)
    clojure.lang.PersistentArrayMap

    关于map - Clojure Maps,键值创建顺序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18456126/

    29 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com