Fork me on GitHub
#meander
<
2022-01-27
>
Ben Sless12:01:50

I have some nested data structure looking approximately like:

[{:x [{:y [{:z [{:w [!k ...]} ...]} ...]} ...]} ...]
Where !k is a string I have another which is a map of {(keyword !k) {:data ?data}} Where I want to produce
[{:x [{:y [{:z [{:w [!k ...] :data ?data} ...]} ...]} ...]} ...]

Ben Sless12:01:42

Turns out to be less simple than I expected

ribelo14:01:28

@ben.sless I am weak in understanding

ribelo14:01:22

you could give example input -> output and I will have a try with that.

Ben Sless14:01:36

in words: sequence of maps, in key x there is a sequence of maps ,,, down to key w In w there is a sequence of strings I want to take that sequence, use it to lookup in another map where each key maps to a sequence, and assoc this sequence in the same map as w

🤯 1
ribelo14:01:21

(m/rewrite [{:a [{:b [{:c ["d" "e" "f"]}]}]}
            {:d 1 :e 1 :f 1}]
  [{:a [{:b [{:c [(m/app keyword !ks) ...]}]}] :as ?m}
   (m/map-of !ks !vs)]
  {& [?m [!ks !vs] ...]})

ribelo14:01:00

@ben.sless something like that?

Ben Sless14:01:32

yes but all the nested sequences can also repeat

Ben Sless14:01:50

More like

(let [lookup {:a [1 2 3]
              :b [4 5 6]
              :c [7 8 9]
              :H '[x y z]}]
  (m/rewrite
    {:x
     [{:y
       [{:z
         [{:w ["a" "b"]}
          {:w ["c" "d"]}]}
        {:z
         [{:w ["e" "f"]}
          {:w ["g" "h"]}]}]}
      {:y
       [{:z
         [{:w ["A" "B"]}
          {:w ["C" "D"]}]}
        {:z
         [{:w ["E" "F"]}
          {:w ["G" "H"]}]}]}]}

    {:x [!x ...]}
    {:x [(m/cata !x) ...]}

    {:y [!x ...]}
    {:y [(m/cata !x) ...]}

    {:z [!x ...]}
    {:z [(m/cata !x) ...]}

    {:w [(m/and !x (m/app keyword !k)) ...]}
    {:w [!x ...] :k [!k ...] :lookup ~lookup}))

Ben Sless14:01:55

But I'm stuck on the final transition

Jimmy Miller14:01:41

You can use [!x ..!n] to capture the number of times something repeats. Helps keep those nested repeats in place.

Ben Sless14:01:59

I'll try again and try to see where I bumped against that specific wall, because I started with it

Ben Sless14:01:34

(m/rewrite
  {:in [{:x
         [{:y
           [{:z
             [{:w ["a" "b"]}
              {:w ["c" "d"]}]}
            {:z
             [{:w ["e" "f"]}
              {:w ["g" "h"]}]}]}
          {:y
           [{:z
             [{:w ["A" "B"]}
              {:w ["C" "D"]}]}
            {:z
             [{:w ["E" "F"]}
              {:w ["G" "H"]}]}]}]}]
   :look
   {:a [1 2 3]
    :b [4 5 6]
    :c [7 8 9]
    :H '[x y z]}}
  {:in [{:x [{:y [{:z [{:w [(m/and !s (m/app keyword !k))
                            ..!nk]}
                       ..!nw]}
                  ..!nz]}
             ..!ny]}
        ..!nx]
   :look {!k [!d ...]}}

  [{:x [{:y [{:z [{:w [!s ..!nk]
                   :d [!d ...]}
                  ..!nw]}
             ..!nz]}
        ..!ny]}
   ..!nx]
  )

Ben Sless14:01:27

accumulating the looked-up values doesn't work right, I'm probably missing something

Jimmy Miller14:01:22

(on my phone). Memory variables don't join like that. You'd want to assign :look to something and do something like (m/app get lookup) Can't think of the right way right now. But will try to play with it later if I have time at the computer and no one else already solved it.

Ben Sless15:01:09

Very close now

(let [lookup {:a [1 2 3]
              :b [4 5 6]
              :c [7 8 9]
              :H '[x y z]}
      f (fn [x] (get lookup (keyword x)))]
  (m/rewrite
    {:x
     [{:y
       [{:z
         [{:w ["a" "b"]}
          {:w ["c" "d"]}]}
        {:z
         [{:w ["e" "f"]}
          {:w ["g" "h"]}]}]}
      {:y
       [{:z
         [{:w ["A" "B"]}
          {:w ["C" "D"]}]}
        {:z
         [{:w ["E" "F"]}
          {:w ["G" "H"]}]}]}]}

    {:x [!x ...]}
    {:x [(m/cata !x) ...]}

    {:y [!x ...]}
    {:y [(m/cata !x) ...]}

    {:z [!x ...]}
    {:z [(m/cata !x) ...]}

    {:w [(m/and !x (m/app f !d)) ...]}
    {:w [!x ...] :d [!d ...]}))

Ben Sless15:01:06

Now :d is [[1 2 3] [4 5 6]] for a b and [[7 8 9] nil] for c d

Ben Sless15:01:15

just need to figure out how to... gather?

Ben Sless15:01:08

Aha!

(let [lookup {:a [1 2 3]
              :b [4 5 6]
              :c [7 8 9]
              :H '[x y z]}
      f (fn [x] (get lookup (keyword x) []))]
  (m/rewrite
    {:x
     [{:y
       [{:z
         [{:w ["a" "b"]}
          {:w ["c" "d"]}]}
        {:z
         [{:w ["e" "f"]}
          {:w ["g" "h"]}]}]}
      {:y
       [{:z
         [{:w ["A" "B"]}
          {:w ["C" "D"]}]}
        {:z
         [{:w ["E" "F"]}
          {:w ["G" "H"]}]}]}]}

    {:x [!x ...]}
    {:x [(m/cata !x) ...]}

    {:y [!x ...]}
    {:y [(m/cata !x) ...]}

    {:z [!x ...]}
    {:z [(m/cata !x) ...]}

    {:w [(m/and !x (m/app f [!d ...])) ...]}
    {:w [!x ...] :d [!d ...]}))

Ben Sless16:01:53

not a fan of this solution though, so if you come up with something better, please share

Richie16:01:11

Not much but it looks like this works

(m/rewrite
     thing

     {:w [(m/and !x (m/app f [!d ...])) ...]}
     {:w [!x ...] :d [!d ...]}

     {(m/and ?k (m/or :x :y :z)) [!x ...]}
     {?k [(m/cata !x) ...]})

Ben Sless16:01:01

more concise, less explicit about the shape of the data