记录可以保证顺序时的顺序吗?

时间:2018-06-24 23:13:51

标签: clojure record

我正在编写一些代码,需要在记录的每个值上map format。为了省去重复的写作,如果我可以依赖具有固定顺序的记录,那将非常方便。这基本上是现在的样子:

(defrecord Pet [health max-health satiety max-satiety])

(let [{:keys [health max-health satiety max-satiety]} pet
        [h mh s ms] (mapv #(format "%.3f" (double %))
                          [health max-health satiety max-satiety])]
  ...)

理想情况下,我想用vals来写:

(let [[h mh s ms] (mapv #(format "%.3f" (double %)) (vals pet))]
  ...)

但是我找不到关于seq时记录是否有保证顺序的任何确定来源。根据我的测试,他们似乎需要订购。我尝试创建海量记录(以防小记录依赖排序的集合):

(defrecord Order-Test [a b c d e f g h i j k l m n o p q r s t u v w x y z
                       aa bb cc dd ee ff gg hh ii jj kk ll mm nn oo pp qq rr ss tt uu vv ww xx yy zz])

(vals (apply ->Order-Test (range 52)))
=> (0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51)

他们似乎确实维持秩序。

任何人都可以验证吗?


对于这种确切的情况,我想我可以reduce-kv结束记录并重新关联val,然后对其进行解构。但是,那将变得非常庞大。我现在也很好奇,因为我什么都找不到。

1 个答案:

答案 0 :(得分:4)

与Clojure中的许多内容一样,由于没有规范,因此不能保证。如果它不在记录的文档字符串中,则您要承担后果自负,即使在当前版本的Clojure中确实如此也是如此。

但是我也要说:从哲学上讲,这并不是真正记录 mean 的内容。记录字段应该具有各自的域语义,并且看起来在您的记录中确实如此。像“拿走该记录的N个有意义的字段,并对其全部进行统一处理”这样的操作是正确的事情,当您将其说明时,便会感到惊讶。

您至少可以做一些您想做的事,而冗余度要小一些

(let [[h mh s ms] (for [k [:health :max-health, :satiety :max-satiety]]
                    (format "%.3f" (get pet k)))]
  ...)

我个人会说您对域的建模错误:您显然有一个“资源”(健康和饱腹感)概念,该概念既有“当前”值又有“最大值”。那些应该按资源分组,例如

{:health {:current 50 :max 80}
 :satiety {:current 3 :max 10}}

这样做之后,我会说宠物的“资源集”实际上只是一个地图字段,而不是它包含的N个资源的N个字段。这样,整个记录字段的排序问题就根本没有出现。