Fork me on GitHub
#meander
<
2021-06-29
>
greg16:06:02

Hi, I'm trying to integrate meander in my project and wandering how to transform

{:AAA {:prop1 ["A" "B"]     :prop2 [1 2 3 4]}
 :BBB {:prop1 ["X" "Y" "Z"] :prop2 [8 9]}}
into
{:prop1 {:AAA ["A" "B"]
         :BBB ["X" "Y" "Z"]}
 :prop2 {:AAA [1 2 3 4]
         :BBB [8 9]}}
I'm using it for the first time, so a bit struggling with it. The best I end up is this:
(m/search {:AAA {:prop1 ["A" "B"] :prop2 [1 2 3 4]}
           :BBB {:prop1 ["X" "Y" "Z"] :prop2 [8 9]}}
          {?topkey {:prop1 ?prop1v :prop2 ?prop2v}}
          {:prop1 {?topkey ?prop1v}
           :prop2 {?topkey ?prop1v}})

; => {:prop1 {:AAA ["A" "B"]}, :prop2 {:AAA ["A" "B"]}} 
;    {:prop1 {:BBB ["X" "Y" "Z"]}, :prop2 {:BBB ["X" "Y" "Z"]}}
Is there a way to perform deep merge out of the box here?

noprompt17:06:34

@grzegorz.rynkowski Welcome. I’ve seen this problem before and I would say that Meander alone would not be a good fit. The recommendation for this problem is to use a combination of Meander and Clojure.

(def result
  (m/search {:AAA {:prop1 ["A" "B"]
                   :prop2 [1 2 3 4]}
             :BBB {:prop1 ["X" "Y" "Z"]
                   :prop2 [8 9]}}
    {?a {?b ?c}}
    [[?b ?a] ?c]))
;; =>
([[:prop1 :AAA] ["A" "B"]]
 [[:prop2 :AAA] [1 2 3 4]]
 [[:prop1 :BBB] ["X" "Y" "Z"]]
 [[:prop2 :BBB] [8 9]])

(reduce (fn [m [p v]] (assoc-in m p v)) {} result)
;; =>
{:prop1 {:AAA ["A" "B"], :BBB ["X" "Y" "Z"]},
 :prop2 {:AAA [1 2 3 4], :BBB [8 9]}}

noprompt18:06:20

Comparing the m/search to what you might do in Clojure (input is example map):

(mapcat (fn [[a m]] (map (fn [[b c]] [[b a] c]) m)) input)
(m/search input {?a {?b ?c}} [[?b ?a] ?c])

noprompt18:06:58

To produce the intermediate sequence of [[b a] c] .

noprompt18:06:48

A quick (time (dotimes [n 1000] (doall form))) between the two lines above, on my machine, show that Meander is, on average, about 5ms slower than vanilla Clojure. Depending on your goals that could be acceptable.

noprompt18:06:22

Certainly I would say the m/search is easier to understand than the combination of mapcat and map. If you have more cases to consider, for example, a key that has a non map value, Meander can adjust to that easily.

greg19:06:20

Thanks for the thorough explanation. Certainly it is easier to understand than mapcat + map, and quite elegant, especially for a generic transformations when properties names are irrelevant. Expressivity was the key reason why tried to use Meander at the first place. Although in my particular case, I ended up with simple reduce:

(reduce (fn [{:keys [prop1 prop2]} [k v]]
          {:prop1 (assoc prop2 k (:prop1 v))
           :prop2 (assoc prop1 k (:prop2 v))}) {} input))
It is just simpler, more concise, and in this particular case where properties names are known, it is easier to reason it. I will keep Meander in mind though. It looks like a great tool.

noprompt19:06:54

That makes perfect sense to me. 🙂

noprompt18:06:37

(m/search (assoc input :CCC "Yarn")
  {?a {?b ?c}}
  [[?b ?a] ?c]

  {?a ?c}
  [[?a] ?c])
;; =>
(,,, [[:CCC] "Yarn"])

noprompt18:06:10

@markaddleman Do you still have the within examples lying around? Slack has truncated that discussion and I wanted to move it GH.

markaddleman18:06:48

I'm using within in a dev project. I can easily reconstruct examples

noprompt18:06:26

If you’re able to open a discussion on GH, do so, if not, I shall create one for this topic. 🙂

markaddleman18:06:49

Sure I'm picking that project back up later today or tomorrow and I'll open an issue with it

noprompt18:06:17

I want to reserve issues for items that have an action plan or bugs, and use discussions for ideas and, um, discussions. 😛

greg19:06:39

@noprompt Maybe the clojurians archive can help here: https://clojurians-log.clojureverse.org/meander/ I think it's indexable by Google, so it might be possible to search through it

👍 2
ribelo19:06:06

@noprompt I'm out for the rest of the week. I'll definitely do a PR when I get back.

noprompt19:06:16

OK. I look forward to it. Have a great week! 😉

noprompt23:06:49

I know this is overdue. And maps will get the same treatment.

noprompt23:06:34

I suspect this feature will be more useful for rewriting.