meander

All things about https://github.com/noprompt/meander Need help and no one responded? Feel free to ping @U5K8NTHEZ
grounded_sage 2020-03-23T16:55:28.008300Z

How would you tackle this transform

(m/rewrite  {:Data
               {:FirstName "Bob"
                :CommunicationChannels [{:ChannelType {:Name "EMail"}
                                         :Content "<mailto:bob@no-mail.com|bob@no-mail.com>"}
                                        {:ChannelType {:Name "Phone"}
                                         :Content "5555-0000"}
                                        {:ChannelType {:Name "EMail"}
                                         :Content "<mailto:bob@other-no-mail.com|bob@other-no-mail.com>"}]}}
              {:Data
               {:FirstName ?first-name
                :CommunicationChannels [{:ChannelType {:Name !comm-channel-type}
                                         :Content !comm-channel-content} ...]}}
              {:first_name ?first-name
               :CommunicationChannels [{!comm-channel-type !comm-channel-content} ...]})
Such that the result is.
{:first_name "Bob"
 :email "<mailto:bob@no-mail.com|bob@no-mail.com>"
 :email_2 "<mailto:bob@other-no-mail.com|bob@other-no-mail.com>"
 :phone "5555-0000"
 :phone_2 nil}

jimmy 2020-03-23T16:58:32.009600Z

Is it just up to two emails and phones or n emails and phones?

grounded_sage 2020-03-23T17:01:43.012Z

That is the annoying part. I am shaping it to a flat structure which goes into SQL and CSV. Perhaps a solution which has up to 2 and one that can have variable would be good.

grounded_sage 2020-03-23T17:03:52.013100Z

This is what exists in the db actually.

phone_number,
   phone_number_2,
   mobile_number,
   mobile_number_2,
   email,
   email_2,

grounded_sage 2020-03-23T17:07:14.018100Z

At present I’m not 100% sure where placement of nil values will occur. Process is. Folder full of JSON files -> Meander to get values of interest -> Turn into single or multiple CSV’s from that JSON -> Generate db tables from CSVs -> Query them with SQl and perform secondary transform with Meander if necessary.

jimmy 2020-03-23T17:07:55.019200Z

That makes it a lot easier. I won't be able to write up a solution right now. There will be a tiny complication with map ordering. But other than that I think it shouldn't be two bad. My recommendation for a first stab at it is to use or to capture the different types in different memory variables.

grounded_sage 2020-03-23T17:13:16.021100Z

So first Meander step is flattening JSON files and splitting up the data so it fits with the rest of our CSV etl workflow.

grounded_sage 2020-03-23T17:13:53.021500Z

@jimmy no rush 😄

grounded_sage 2020-03-23T17:15:31.022200Z

I have a lot of other very nested JSON files so I am hoping when I see a solution it enlightens me as to how I can do the rest.

jimmy 2020-03-23T19:32:12.022800Z

@grounded_sage

(m/rewrite {:Data
            {:FirstName "Bob"
             :CommunicationChannels [{:ChannelType {:Name "EMail"}
                                      :Content "<mailto:bob@no-mail.com|bob@no-mail.com>"}
                                     {:ChannelType {:Name "Phone"}
                                      :Content "5555-0000"}
                                     {:ChannelType {:Name "EMail"}
                                      :Content "<mailto:bob@other-no-mail.com|bob@other-no-mail.com>"}]}}
  {:Data
   {:FirstName ?first-name
    :CommunicationChannels [(m/or
                             {:ChannelType {:Name "EMail"}
                              :Content !emails}
                             {:ChannelType {:Name "Phone"}
                              :Content !phones}) ...]}}
  {&amp; [[:first_name ?first-name]
      [:email !emails]
      [:email_2 !emails]
      [:phone !phones]
      [:phone_2 !phones]]})

grounded_sage 2020-03-24T08:53:21.031100Z

Is there a reason for the vector pairs here?

grounded_sage 2020-03-24T08:53:49.031300Z

As I just tried

{&amp; {:first_name ?first-name, 
                 :email !emails, 
                 :email_2 !emails, 
                 :phone !phones, 
                 :phone_2 !phones}}
and it appears to give the same result.

jimmy 2020-03-24T13:58:00.031500Z

Yes because as your map grows it will be parsed out of order and the memory variables will be in the wrong place. I think it is 8 elements when that happens?

1👍
grounded_sage 2020-03-24T18:47:50.031700Z

Ah I see.

niclasnilsson 2020-03-23T20:40:32.024700Z

Hi! A little bit of an odd example (it’s been minimized from a much larger example). Isn’t m/app called from the action part of a match?

(defn -&gt;h [v]
  (case v
    1 {:info "some info"}
    2 {:extra "something else"}))

(defn foo [data]
  (m/match
    data

    {:a ?a
     :b ?b}

    {:foo
     (m/app str ?a
       merge
       {}
       (m/app -&gt;h ?a)
       (m/app -&gt;h ?b))}))

(foo {:a 1 :b 2})

;; expected
;; {:foo {:info "some info" :extra "something else"}}

niclasnilsson 2020-03-23T20:42:18.026100Z

The use case is that I have a value in the pattern part (like ?a and ?b) that I need to merge (after some transformation) in the action.

niclasnilsson 2020-03-23T20:58:37.026500Z

Never mind, solved it with m/rewrite!

niclasnilsson 2020-03-23T21:02:09.027200Z

And then realized that it could be used with m/match using just merge, mot m/app.

jimmy 2020-03-23T21:03:35.028800Z

Yeah for match the right hand side is just normal clojure code. With rewrite it is a substitution.

noprompt 2020-03-23T22:50:42.030200Z

Just wanted to share something fun from progress being made on the zeta branch showing a properly greedy * and the concept of the fold (which is still a work in progress).

(solve '[1 8 2 -5 3 4]
       (mz/with [%min (mz/fold *min 0 clojure.core/min)
                 %max (mz/fold *max 0 clojure.core/max)]
         [(mz/* (mz/and %min %max)) . !zs ...]))
;; =&gt;
({#meander.runtime.zeta/fold-variable [*min ,,,] -5,
  #meander.runtime.zeta/fold-variable [*max ,,,] 8,
  #meander.runtime.zeta/memory-variable !zs []})

noprompt 2020-03-23T22:51:42.031Z

*min is -5, *max is 8, and !zs is empty because the greedy star ate its lunch. 🙂