Clojure macro that will conserve associative map order

后端 未结 2 468
无人及你
无人及你 2021-01-18 07:23

To preface, I am on Windows 7 (64-bit), running Java version 6 (update 33) using clooj as my IDE. I have not tried to reproduce my problem in any other system. I am experien

相关标签:
2条回答
  • 2021-01-18 07:33

    The problem as stated is not soluble. Maps are defined to have no order; any order you see in array-map is coincidental. If you require that your macro receive a map, you have already lost the information you desire.

    0 讨论(0)
  • 2021-01-18 07:45

    you can make your map with array-map

    user> (map vec (array-map 1 2 3 4 5 6))
    ([1 2] [3 4] [5 6])
    

    or with a larger map

    user> (map vec (apply array-map (range 50)))
    ([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])
    

    as a bonus you can avoid using a macro, which is useful because macros are not first-class and don't compose well*


    a note on your first comment from the documentation on array map

     Note that an array map will only maintain sort order when un-'modified'. 
     Subsequent assoc-ing will eventually cause it to 'become' a hash-map.

    If you find yourself depending on the order of keys in your maps you may want to consider if a sorted-map will get you what you need. It will scale better than an array-map. In the above example the output is the same:

    (map vec (apply sorted-map (range 5000)))
    [0 1] [2 3] ... [4998 4999]
    

    *this is my opinion


    EDIT:

    a time comparason of sorted-map vs. array-map

    user> (time (dorun (map vec (apply sorted-map (range 500000)))))
    "Elapsed time: 391.520491 msecs"
    nil
    user> (time (dorun (map vec (apply array-map (range 500000)))))
    "Elapsed time: 674517.821669 msecs"
    
    0 讨论(0)
提交回复
热议问题