This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
Hello everyone, if I wanna recursively traverse a structure just for a side effect what should I use?
Is it select with view
or something else?
I was reluctant of adding the word "recursively" because I knew that I'll get a link to recursive specter 😅 I know how to do recursion in specter, my question was mainly about the effects and recursion was more of a background information.
It was inevitable 😂. We use recursive navs also. For side effects, could you use a command pattern to keep it pure? If so, you can reduce using the recursive nav.
I want to print tuples of a map with each of it's value:
(do-some-magic {:a 1, :b 2}) =>
; [{:a 1, :b 2}, 1]
; [{:a 1, :b 2}, 2]
Hmm, still don't have enough context to grok your problem. If trying to print a tree, we have done that using a zipper with side effects. Would that work?
Sure, i think...
I was reluctant of adding the word "recursively" because I knew that I'll get a link to recursive specter 😅 I know how to do recursion in specter, my question was mainly about the effects and recursion was more of a background information.
Hello again! 😊
I'm interested in writing a Specter code snippet that takes a list of maps as input and performs a merging operation using (conj [])
.
The goal is to create a resulting map where each key holds a vector
containing corresponding values from the input maps. To illustrate, the
transformation should turn [{:a 1 :b 2} {:a 3 :b 4} {:a 5 :b 6}]
into {:a [1 3 5], :b [2 4 6]}
.
As
a bonus, if all the values within the input maps are themselves maps,
I'd like to extend this behavior recursively. I've already implemented a
solution for this using merge-with
,
but I wanted to try out the same process using Specter. This will
also serve as an opportunity to compare the performance of the two
approaches.
Thanks in advance
I think you’ll get more responses if you explain what you tried, what worked, and what didn’t work.
Today I had an implementation of the sort:
(->> maps
(select [ALL ALL])
(group-by second)
(transform [MAP-VALS] #(select [ALL LAST] %))
But it was way slower than the simple clojure implementation so I dropped that.In general, I think you’ll get more of a benefit if you can make the the transformation in one step.
I did that as well using subselect and transformed, but it performed even worse. I think specter is just not a great fit for those kinds of transformations (+ reduce)
If you rewrite your spec version to not require the transformation after the group-by, that might help.
I tried to think of ways to do that using only specter but I couldn't find any, that's why I asked here for ideas 😅
Right, but you didn't include any of the methods you tried.
When I asked I wasn't able to think of any idea so there weren't any methods to write about. Only when I relaxed my constraints today (after I bumped) I wrote the attempt using group-by.
What's the reason behind wanting this particular transformation? Why does it need to be fast?
There are various libraries that have faster versions of group-by
.
If you care about performance, then you'll probably want to do some amount of profiling.
It's a core operation in our code that is currently a performance bottleneck
We did profiling that's how we zeroed in on that code piece
But that code is already after performance refactoring so it might be solved.
The reason I ask is there are many ways to approach the problem and the solution will depend on these types of factors.
If you are still looking for alternatives, you can also look at https://github.com/cgrand/xforms and https://github.com/cnuernber/ham-fisted which both have alternate implementations of group-by
that could help speed things up.
Actually the group-by implementation was way slower than another implementation of iterating on all the keys. And that was a bit slower than merge-with (that actually surprised me).
group-by
, merge
, and merge-with
are not the fastest options which is why there are several alternate implementations.
ham looks very interesting and relevant to me, I'll try it. Thank you 🙏:skin-tone-3:
Now I see ham only support clj (I need cljs) what a shame 😔
nothing? 🥲