meander

2021-09-10T00:25:36.049100Z

(m/rewrites {:x {:y [:a :b :c]
                         :q [:a :b :c]}}
          {!xs {!ys (m/scan :b)}}
          [[!xs !ys] ...])
Is there any way to do this without using rewriteS but with just simple rewrite?

noprompt 2021-09-10T16:33:31.055900Z

I think. Lemme try…

Richie 2021-09-10T01:00:30.050400Z

Why does it work with r1 and not with r2?

Richie 2021-09-10T01:01:43.050800Z

Sorry, I'm also having trouble creating a more minimal example. I feel in over my head.

2021-09-10T01:13:42.051Z

There are a multiple keys in map r2 :active and scan can't handle it

2021-09-10T01:14:36.051200Z

Unfortunately I'm writing from my phone so I can't help you right now

Richie 2021-09-10T01:15:53.051400Z

No trouble. That's already very helpful. Thank you!

2021-09-10T07:18:26.051600Z

(let [r1 [[0 {:active {:a {:ids [{:business "123"}]}}}]
          [1 {:active {:d {:ids [{:business "567"}]}}}]]
      r2 [[0 {:active {:a {:ids [{:business "123"}]}
                       :b {:ids [{:business "234"}]}}}]
          [1 {:active {:d {:ids [{:business "567"}]}
                       :c {:ids [{:business "678"}]}}}]]
      f (fn [arg]
          (m/rewrite arg
            [[(m/and !xs !ys) {:active (m/map-of _ {:ids [{:business !ids}]})}] ...]
            [[[!xs !ids] [!ys !ids] ...]]))]
  (f r1)                                ;; [[0 "123"] [1 "567"]]
  (f r2)                                ;; [[0 "123"] [0 "234"] [1 "567"] [1 "678"]]
  )

2021-09-10T07:19:06.051800Z

Surely it can be done more simply

2021-09-10T07:19:33.052Z

@rgkirch

Richie 2021-09-10T18:37:40.058600Z

Hey. I figured some things out. First I got the answer I wanted from this smaller example:

(let [r2 [{:a [{:word "123"}
               {:word "abc"}]
           :b [{:word "234"}
               {:word "bcd"}]}]
      f (fn [arg]
          (m/find
            arg
            (m/gather (m/map-of _ (m/gather {:word !a})))
            !a))]
  (f r2))
  ;; => ["123" "abc" "234" "bcd"]
But it didn’t seem like I was doing this correctly since I think I should be able to search with a logic var instead of using a memory var like that. The example for scan gave me the idea to treat a map as a seq of MapEntry.
(m/search {:x 1 :y 2 :z 3}
  (m/scan [?a ?b])
  {?b ?a})
;; => ({1 :x} {2 :y} {3 :z})
So then I got this working code:
(let [r2 [{:a [{:word "123"}
               {:word "abc"}]
           :b [{:word "234"}
               {:word "bcd"}]}]
      f (fn [arg]
          (m/search
            arg
            (m/scan (m/scan [_ (m/scan {:word ?a})]))
            ?a))]
  (f r2))

  ;; => ("123" "abc" "234" "bcd")
Going back to an example of my actual problem:
(let [r2 [[0 {:active {:a {:ids [{:business "123"}
                                 {:business "aha"}]}
                       :b {:ids [{:business "234"}]}}}]
          [1 {:active {:d {:ids [{:business "567"}]}
                       :c {:ids [{:business "678"}]}}}]]
      f (fn [arg]
          (m/search
            arg
            (m/scan [?t {:active (m/scan [_ {:ids [{:business !a} ...]}])}])
            [?t !a]))]

  (f r2))
;; => ([0 ["123" "aha"]] [0 ["234"]] [1 ["567"]] [1 ["678"]])
I actually want to get a result like ([0 [“123” “aha” “234”]] [1 [“567" “678”]]) but I haven’t figured it out yet. Thank you all of you for making such a sick library and for the great support.

🎉 1
Richie 2021-09-10T18:44:07.059Z

@huxley Thanks for the working example. I didn’t know about map-of until I saw you use it. After that, I cloned the repo and poked around reading through some of the docstrings. Ultimately, I don’t think I want to use and since I don’t know how many things I’ll have there; I could have made a better question than to just ask why it was broken, haha. Thanks again.

Ben Sless 2021-09-10T09:48:19.052900Z

Wanted to share something cool and ask if you think I made any mistakes or it could be improved - beta reduction of tools.analyzer ast node:

(m/rewrite
    node
    {:op :invoke
     :args [!args ..?n]
     :fn {:op :fn
          :methods
          [{:fixed-arity ?n
            :variadic? false
            :form _ :arglist _ :tag _ :o-tag _ ;; rudely ignore
            :params
            [{:local _ :arg-id _
              & !params} ...]
            :body ?body}
           ..1]} ;; there can be only one!
     & ?rest}
    {:op :let
     :children [:bindings :body]
     :bindings
     [{:init !args
       :local :let
       :children [:init]
       & !params} ...]
     :body ?body})

2021-09-10T10:42:10.053Z

I don't know what it does but it looks cool

2021-09-10T10:43:44.053200Z

_ can be omitted if they are not for readability

2021-09-10T10:44:18.053400Z

whereas, if these are the required things that should be there, then it's a good idea to wrap in (m/some)

Ben Sless 2021-09-10T11:53:05.053600Z

It's a poor man's dissoc but you're right, I should rewrite it

Ben Sless 2021-09-10T11:53:38.053800Z

what it does: ((fn [x] B) E) -> (let [x E] B)

noprompt 2021-09-10T16:34:36.056100Z

Awesome! This is definitely one of the use cases I was designing for. 🙂

Ben Sless 2021-09-10T16:37:59.056700Z

Success :)

Ben Sless 2021-09-10T13:25:29.054400Z

Is it possible to perform a recursive search and substitution inside a bound variable?

Richie 2021-09-15T14:52:38.067900Z

Just found https://clojurians-log.clojureverse.org/meander a log of clojurians slack.

Ben Sless 2021-09-13T07:05:20.064400Z

OPened a discussion for both

schmee 2021-09-10T13:32:47.054500Z

not entirely sure this is what you’re looking for but m/cata might help: https://github.com/noprompt/meander/blob/epsilon/doc/cookbook.md#recursion-reduction-and-aggregation

Ben Sless 2021-09-10T13:44:39.055Z

cata still assumes I know the shape of the input (sort of). In the case where I don't want to specify all the possible patterns, is there a generic walk?

2021-09-10T13:56:20.055200Z

Try strategy namespace

2021-09-10T13:58:23.055400Z

Probably bottom-up is what you're looking for

Ben Sless 2021-09-10T14:09:31.055600Z

I'd still have to specify all the patterns I want to search over 😞

noprompt 2021-09-10T16:35:55.056300Z

Ben, are you able to layout in more detail what your idea/goal is? I’m not sure I totally follow.

Ben Sless 2021-09-10T16:37:35.056500Z

Sure, I'm trying to implement optimization passes on tools.analyzer output. Beta reduction, copy and constant propagation

noprompt 2021-09-10T16:43:17.056900Z

Cool. I follow this. I was looking for an example/sketch (could be contrived) of the problem and what you would like the solution to look like/the result, etc.

noprompt 2021-09-10T16:44:58.057100Z

We do need a more general walking mechanism that isn’t strategy based. I have some ideas about that but none that I can invest time in right now.

noprompt 2021-09-10T16:56:11.057400Z

One of the things that I’ve done in the past is write rules like this

(m/rewrite form
  [::special def ?tail]
  {:type :def  ,,,}

  ((m/pred special-symbol? ?symbol) & tail)
  (m/cata [::special ?symbol ?tail]))
essentially emulating a function/function call inside the system.

Ben Sless 2021-09-10T16:59:43.057600Z

You could write a HOF which returns a walker

Ben Sless 2021-09-10T17:02:11.057800Z

Bottom up and top down are a special case of post/pre walk derived from it

noprompt 2021-09-10T17:07:05.058Z

Yeah.

noprompt 2021-09-10T17:37:25.058200Z

I wanted to mention earlier, Github discussions are available too if you want to jot down something a bit more long form that lays out the full scope of the problem.

Ben Sless 2021-09-10T18:02:10.058400Z

Probably will, thank you 🙂

Richie 2021-09-10T18:48:12.059200Z

Oh nice. I was upset that slack limits the conversation history since I’d like to dig through the history for more examples.

noprompt 2021-09-10T19:07:57.059400Z

Please post there. And, if you do, share the link here as well.

noprompt 2021-09-10T19:09:45.059600Z

Honestly, I should probably do that too.

Ben Sless 2021-09-10T19:26:41.059800Z

You could probably make half a cookbook by scraping the history of this channel on the log. zulip?

Richie 2021-09-10T19:42:01.060400Z

I put my question in gh discussions. https://github.com/noprompt/meander/discussions/208

noprompt 2021-09-10T19:49:34.061Z

> Hey! I hope you’re having a great day. This sentence. 😄

noprompt 2021-09-10T19:50:24.061300Z

Also the title. High marks. 100%

2021-09-15T19:56:20.070800Z

regarding the learning curve, I don't think there is anything that can be done about it

2021-09-15T19:56:37.071Z

meander is simple but not easy

2021-09-15T19:58:02.071200Z

some concepts like cata or with just have to pop in our head

Ben Sless 2021-09-15T20:00:37.071600Z

Is there anything I can read which would help me understand cata? Sometimes I find original papers on subjects make it click for me. Did so for HAMTs and CSP

2021-09-15T20:00:58.071800Z

cata is simply recursion

2021-09-15T20:01:54.072Z

of the non-obvious things that came out of using cata was discovering that you can put the processed data into a vector, where the first element is whatever tells you what to do with it

Ben Sless 2021-09-15T20:03:32.072200Z

I understand all of these words, but have no way to translate them to actionable knowledge yet. Maybe 11pm is not the time

2021-09-15T20:05:21.072400Z

I guess it just requires some practice

2021-09-15T20:11:38.072700Z

I would start by looking at all the examples that are in the meander repo. Reading through all the tests also gave me a lot.

Ben Sless 2021-09-15T20:14:31.072900Z

I read the cata tests several times. The trivial cases made sense but didn't click for me yet. No worries, I shall bang my head against that wall until it breaks

2021-09-15T20:16:13.073100Z

I've been through it, and after some head-banging, the tinnitus even stops

😆 1
2021-09-15T20:17:20.073400Z

in general I appreciate your work, e.g. on malli, a lot can be learned by reading the code

2021-09-15T20:17:39.073600Z

I think you have a perversion to numbers and like to speed up other people's code 🙃

Ben Sless 2021-09-15T20:21:13.073800Z

Ha, guilty

Ben Sless 2021-09-15T20:21:22.074Z

And thank you 😃

2021-09-15T20:23:22.074200Z

you'll probably find something to do once you get into the meander code

Ben Sless 2021-09-15T20:24:45.074400Z

Ben Sless 2021-09-15T20:25:42.074800Z

Besides, I want to use meander to speed up other code. All the code, if possible 🙂

2021-09-15T20:26:13.075Z

well, that's what I'm currently trying to do

2021-09-15T20:26:29.075200Z

and it's addictive

Ben Sless 2021-09-15T20:26:33.075400Z

Speed up meander or use meander to write a compiler?

2021-09-15T20:27:00.075600Z

yes

Ben Sless 2021-09-15T20:27:00.075800Z

> and it's addictive Absolutely

Ben Sless 2021-09-15T20:27:07.076Z

numbers go woosh

2021-09-15T20:27:24.076200Z

dopamine over 9000!!!

Ben Sless 2021-09-15T20:28:52.076400Z

have you applied meander to tools.analyzer ast?

2021-09-15T20:29:34.076600Z

not yet

2021-09-15T20:30:04.076800Z

code in meander can be fully declarative, imho it is often much more readable than pure clojure, moreover it is easy to come back to, because, omits some concepts like cata, it is clear and understandable

2021-09-15T20:31:04.077Z

for now, I'm learning meander mostly by writing doxa and poking around in meander itself

Ben Sless 2021-09-15T20:35:47.077200Z

it seems like a very good fit. There are some Haskell papers which are relevant

Ben Sless 2021-09-15T20:36:21.077400Z

https://github.com/noprompt/meander/discussions/212 this example

2021-09-15T20:37:29.077600Z

wait, because I don't think I quite caught on before

2021-09-15T20:38:04.077800Z

You literally want to use meander to rewrite other people's code

Ben Sless 2021-09-15T20:38:21.078Z

yes

Ben Sless 2021-09-15T20:38:23.078200Z

any code

Ben Sless 2021-09-15T20:38:44.078400Z

An alternative compiler

2021-09-15T20:39:17.078600Z

crazy idea

Ben Sless 2021-09-15T20:39:24.078800Z

thanks 😄

2021-09-15T20:39:26.079Z

I'm in xD

Ben Sless 2021-09-15T20:41:05.079200Z

Links here are a good starting point https://wiki.haskell.org/Performance/GHC#Looking_at_the_Core

Ben Sless 2021-09-15T20:41:18.079400Z

and the video linked in the discussion

Ben Sless 2021-09-15T20:41:28.079600Z

https://www.youtube.com/watch?v=uR_VzYxvbxg

👍 1
2021-09-15T20:42:20.079900Z

it's a bit beyond my homegrown programming knowledge, but I'm happy to watch

Ben Sless 2021-09-15T20:42:52.080100Z

I did not study computer science 🤷

Ben Sless 2021-09-15T20:43:12.080300Z

If you can get meander, you can get Core

Ben Sless 2021-09-15T20:43:34.080500Z

Besides Big Lambda type constructors don't ask me about those types are hard

2021-09-15T20:44:12.080700Z

haskel sounds like something you need a PhD to understand

Ben Sless 2021-09-15T20:44:55.080900Z

Yes, which is why I'm not trying to understand Haskell, but the intermediate language and how they transform it for optimizations

👍 1
2021-09-15T20:45:06.081100Z

Meanwhile, I've got to go. Thanks for the chat.

Ben Sless 2021-09-15T20:45:12.081300Z

gladly

Ben Sless 2021-09-15T20:45:28.081500Z

sleep time for me 🌃

noprompt 2021-09-21T16:15:06.083700Z

Core is cool. 😎

Ben Sless 2021-09-21T16:17:41.083900Z

I wish I could take a sabbatical to work on this

Richie 2021-09-10T20:02:04.061600Z

Haha, thanks. I was feeling punchy after punching away at the same problem all day.

Ben Sless 2021-09-10T20:04:53.061800Z

New meaning of "using X in anger"?

🤣 1
noprompt 2021-09-10T20:06:26.062Z

Ah, yeah, that can be frustrating. And I know there is a learning curve. Buuuut, hopefully, we can help. 🙂

Ben Sless 2021-09-10T20:13:06.062300Z

One day I'll understand m/cata then I'll be able to just communicate telepathically or something

Richie 2021-09-10T20:17:11.062500Z

It seems like the learning curve is steeper than most new things that I encounter while programming but the payoff also seems much greater than the usual new thing. So much so that the ratio of cost to benefit weighs heavily in favor of learning and using it. It’s existence and this community are also gifts so I can’t begin to be critical. I’m not actually angry; I’m just playing it up for the humor. 🙂

noprompt 2021-09-10T20:30:47.062700Z

> the learning curve is steeper … the ratio of cost to benefit weighs heavily in favor of learning and using it This is a perspective I think others in the channel share. Improving the overall experience and reducing the learning curve/providing help are priorities. For me, the criticism is inspiring actually, I’ve just had a rough time the past year dealing with burn out from software, and $pandemic_related_reasons .

noprompt 2021-09-10T20:31:45.062900Z

But I will say, this channel is awesome. I’m really proud of the folks in here. People are helpful and courteous. “No stupid questions” kind of attitude. 🙂

noprompt 2021-09-10T20:31:57.063200Z

This channel has kept me going!

noprompt 2021-09-10T20:32:18.063400Z

Also, I will try and fill in some explaining on my replies to your question.