meander

All things about https://github.com/noprompt/meander Need help and no one responded? Feel free to ping @U5K8NTHEZ
greg 2021-06-29T16:25:02.080700Z

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?

noprompt 2021-06-29T17:58:34.083300Z

@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]}}

noprompt 2021-06-29T18:06:20.084300Z

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])

noprompt 2021-06-29T18:06:58.084800Z

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

noprompt 2021-06-29T18:11:48.086300Z

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.

noprompt 2021-06-29T18:14:22.088300Z

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.

noprompt 2021-06-29T18:15:37.088600Z

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

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

noprompt 2021-06-29T18:19:10.090400Z

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

markaddleman 2021-06-29T18:19:48.090700Z

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

noprompt 2021-06-29T18:20:26.090900Z

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

markaddleman 2021-06-29T18:20:49.091100Z

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

noprompt 2021-06-29T18:22:17.091300Z

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

markaddleman 2021-06-29T18:22:57.091600Z

πŸ˜„ Sure

2021-06-29T19:21:06.092200Z

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

noprompt 2021-06-29T19:22:16.092300Z

OK. I look forward to it. Have a great week! πŸ˜‰

greg 2021-06-29T19:29:20.092500Z

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.

greg 2021-06-29T19:31:39.092700Z

@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

πŸ‘ 1
noprompt 2021-06-29T19:31:54.092900Z

That makes perfect sense to me. πŸ™‚

2021-06-29T19:34:33.093200Z

thx

noprompt 2021-06-29T23:11:59.093500Z

https://github.com/noprompt/meander/pull/180

noprompt 2021-06-29T23:12:49.094Z

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

noprompt 2021-06-29T23:13:34.094600Z

I suspect this feature will be more useful for rewriting.