代码之家  ›  专栏  ›  技术社区  ›  Carcigenicate

记录能保证顺序吗?

  •  2
  • Carcigenicate  · 技术社区  · 7 年前

    我在写一些代码 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 回复  |  直到 6 年前
        1
  •  4
  •   amalloy    7 年前

    与clojure中的许多东西一样,没有任何保证,因为没有规范。如果它不在记录的docstring中,即使在当前版本的clojure中碰巧是真的,您也要承担风险。

    但我也要说:那不是真正的记录 意思是 ,哲学上。记录字段应该具有单独的域语义,并且看起来在您的记录中它们确实有。当一个像“取下这个记录中的n个明显有意义的字段,并对它们进行统一处理”这样的操作是正确的时候,这是一个很大的惊喜,当你这样做的时候,它应该被阐明。

    你至少可以用更少的冗余来做你想做的事情:

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

    我个人认为,你正在建模你的域名错误:你显然有一个“资源”(健康和饱腹感)的概念,它既有“当前”也有“max”值。应按资源(如

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

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

    推荐文章