(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?I think. Lemme try…
Why does it work with r1 and not with r2?
Sorry, I'm also having trouble creating a more minimal example. I feel in over my head.
There are a multiple keys in map r2 :active and scan can't handle it
Unfortunately I'm writing from my phone so I can't help you right now
No trouble. That's already very helpful. Thank you!
(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"]]
)
Surely it can be done more simply
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.@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.
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})I don't know what it does but it looks cool
_ can be omitted if they are not for readability
whereas, if these are the required things that should be there, then it's a good idea to wrap in (m/some)
It's a poor man's dissoc but you're right, I should rewrite it
what it does:
((fn [x] B) E) -> (let [x E] B)
Awesome! This is definitely one of the use cases I was designing for. 🙂
Success :)
Is it possible to perform a recursive search and substitution inside a bound variable?
Just found https://clojurians-log.clojureverse.org/meander a log of clojurians slack.
OPened a discussion for both
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
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?
Try strategy namespace
Probably bottom-up is what you're looking for
I'd still have to specify all the patterns I want to search over 😞
Ben, are you able to layout in more detail what your idea/goal is? I’m not sure I totally follow.
Sure, I'm trying to implement optimization passes on tools.analyzer output. Beta reduction, copy and constant propagation
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.
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.
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.You could write a HOF which returns a walker
Bottom up and top down are a special case of post/pre walk derived from it
Yeah.
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.
Probably will, thank you 🙂
Oh nice. I was upset that slack limits the conversation history since I’d like to dig through the history for more examples.
Please post there. And, if you do, share the link here as well.
Honestly, I should probably do that too.
You could probably make half a cookbook by scraping the history of this channel on the log. zulip?
I put my question in gh discussions. https://github.com/noprompt/meander/discussions/208
> Hey! I hope you’re having a great day. This sentence. 😄
Also the title. High marks. 100%
regarding the learning curve, I don't think there is anything that can be done about it
meander is simple but not easy
some concepts like cata or with just have to pop in our head
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
cata is simply recursion
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
I understand all of these words, but have no way to translate them to actionable knowledge yet. Maybe 11pm is not the time
I guess it just requires some practice
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.
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
I've been through it, and after some head-banging, the tinnitus even stops
in general I appreciate your work, e.g. on malli, a lot can be learned by reading the code
I think you have a perversion to numbers and like to speed up other people's code 🙃
Ha, guilty
And thank you 😃
you'll probably find something to do once you get into the meander code
Besides, I want to use meander to speed up other code. All the code, if possible 🙂
well, that's what I'm currently trying to do
and it's addictive
Speed up meander or use meander to write a compiler?
yes
> and it's addictive Absolutely
numbers go woosh
dopamine over 9000!!!
have you applied meander to tools.analyzer ast?
not yet
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
for now, I'm learning meander mostly by writing doxa and poking around in meander itself
it seems like a very good fit. There are some Haskell papers which are relevant
https://github.com/noprompt/meander/discussions/212 this example
wait, because I don't think I quite caught on before
You literally want to use meander to rewrite other people's code
yes
any code
An alternative compiler
crazy idea
thanks 😄
I'm in xD
Links here are a good starting point https://wiki.haskell.org/Performance/GHC#Looking_at_the_Core
and the video linked in the discussion
it's a bit beyond my homegrown programming knowledge, but I'm happy to watch
I did not study computer science 🤷
If you can get meander, you can get Core
Besides Big Lambda type constructors don't ask me about those types are hard
haskel sounds like something you need a PhD to understand
Yes, which is why I'm not trying to understand Haskell, but the intermediate language and how they transform it for optimizations
Meanwhile, I've got to go. Thanks for the chat.
gladly
sleep time for me 🌃
Core is cool. 😎
I wish I could take a sabbatical to work on this
Haha, thanks. I was feeling punchy after punching away at the same problem all day.
New meaning of "using X in anger"?
Ah, yeah, that can be frustrating. And I know there is a learning curve. Buuuut, hopefully, we can help. 🙂
One day I'll understand m/cata then I'll be able to just communicate telepathically or something
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. 🙂
> 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 .
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. 🙂
This channel has kept me going!
Also, I will try and fill in some explaining on my replies to your question.