Para comenzar, estoy en Windows 7 (64 bits), ejecutando Java versión 6 (actualización 33) usando clooj como mi IDE. No intenté reproducir mi problema en ningún otro sistema. Tengo experiencia con Clojure, pero no con Java.Clojure macro que conservará la orden de asignación asociativa
Todo el problema que trato de resolver es largo de describir, pero se reduce a esto: digamos que me gustaría hacer una macro que tome un argumento, un mapa asociativo, y devuelva un vector de los elementos del mapa con su orden conservada.
=>(defmacro vectorize-a-map
[associative-map]
(vec associative-map))
=>#'ns/vectorize-a-map
=>(vectorize-a-map {:a 1 :b 2 :c 3 :d 4 :e 5 :f 6 :g 7 :h 8}
=>[[:a 1] [:b 2] [:c 3] [:d 4] [:e 5] [:f 6] [:g 7] [:h 8]]
que funciona, pero añade otro elemento al mapa y el orden meta la pata ...
=>(vectorize-a-map {:a 1 :b 2 :c 3 :d 4 :e 5 :f 6 :g 7 :h 8 :i 9}
=>[[:a 1] [:c 3] [:b 2] [:f 6] [:g 7] [:d 4] [:e 5] [:i 9] [:h 8]]
Creo que he descubierto por qué ocurre esto. Parece que cualquier instancia con 8 o menos elementos se instancia como una PersistentArrayMap, que es exactamente lo que quiero, porque por lo que puedo decir, esta clase conserva el orden. Sin embargo, cualquier elemento con 9 o más elementos se instancia como un PersistentHashMap, que no conserva el orden.
=>(type {:a 1 :b 2 :c 3 :d 4 :e 5 :f 6 :g 7 :h 8}
=>clojure.lang.PersistentArrayMap
=>(type {:a 1 :b 2 :c 3 :d 4 :e 5 :f 6 :g 7 :h 8 :i 9}
=>clojure.lang.PersistentHashMap
Me gustaría que mi macro sea capaz de tomar mapas asociativos de cualquier tamaño, por lo que este es un problema. He intentado con el tipo de insinuación, enlace destructivo, para la comprensión de la lista, y el empalme de unificación, todo sin éxito. Para extraerlo, ninguno de los siguiente trabajo:
(defmacro vectorize-a-map
[^clojure.lang.PersistentArrayMap associative-map]
(vec associative-map))
(defmacro vectorize-a-map
[[& associative-map]]
(vec associative-map))
(defmacro vectorize-a-map
[associative-map]
(vec
(for [x associative-map]
x)))
(defmacro vectorize-a-map
[associative-map]
`(vector [email protected]))
Con este problema juguete presento, me di cuenta que podía simplemente escribir mi macro como tal, y evitar el problema por completo:
=>(defmacro vectorize-kvs
[& elements]
(vec (map vec (partition 2 elements))))
=>#'ns/vectorize-kvs
=>(vectorize-kvs :a 1 :b 2 :c 3 :d 4 :e 5 :f 6 :g 7 :h 8 :i 9)
=>[[:a 1] [:b 2] [:c 3] [:d 4] [:e 5] [:f 6] [:g 7] [:h 8] [:i 9]]
Sin embargo, para el problema actual que estoy tratando de resolver (que no he entrado), es importante (aunque no es 100% necesario) que la macro sea capaz de tomar mapas asociativos. Parece que estoy buscando cómo convertir el argumento en un PersistentArrayMap antes de que algo tenga la posibilidad de sucederle. Puede haber alguna otra vía hacia una solución que simplemente no estoy considerando o consciente.
Investigué lo mejor que he conocido y aún no he encontrado nada útil. ¿Alguien tiene pensamientos/consejos?
la primera regla del macro club es "no escribir una macro" ... (¿puedes adivinar la segunda?) –
Imagino que la segunda regla es: "Cállate. En serio, no escribas una macro". –