specter

2023-08-20T07:59:49.996559Z

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?

2023-08-20T09:05:30.565269Z

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.

steveb8n 2023-08-20T09:21:19.685059Z

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.

steveb8n 2023-08-20T09:21:56.857049Z

Not sure I understand what you mean by side effects in this case?

2023-08-20T09:33:33.605779Z

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]

steveb8n 2023-08-20T09:42:09.145059Z

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?

2023-08-20T09:42:37.303769Z

Sure, i think...

2023-08-20T13:39:26.068409Z

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

2023-08-27T08:33:00.485999Z

nothing? 🥲

phronmophobic 2023-08-27T16:54:08.482929Z

I think you’ll get more responses if you explain what you tried, what worked, and what didn’t work.

2023-08-27T17:08:41.758849Z

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.

phronmophobic 2023-08-27T17:11:06.473119Z

In general, I think you’ll get more of a benefit if you can make the the transformation in one step.

2023-08-27T17:13:39.707489Z

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)

phronmophobic 2023-08-27T17:18:24.291779Z

I tend to only use specter when selection is pretty straightforward and transformations are just modifying the selection. It’s possible that there might be more efficient methods in spec (eg. using collect)

phronmophobic 2023-08-27T17:20:16.118039Z

If you rewrite your spec version to not require the transformation after the group-by, that might help.

2023-08-27T17:24:21.601689Z

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 😅

phronmophobic 2023-08-27T17:24:55.126879Z

Right, but you didn't include any of the methods you tried.

2023-08-27T17:27:13.418649Z

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.

phronmophobic 2023-08-27T17:31:51.757509Z

What's the reason behind wanting this particular transformation? Why does it need to be fast?

phronmophobic 2023-08-27T17:32:31.817669Z

There are various libraries that have faster versions of group-by .

phronmophobic 2023-08-27T17:33:18.050889Z

If you care about performance, then you'll probably want to do some amount of profiling.

2023-08-27T17:34:54.605749Z

It's a core operation in our code that is currently a performance bottleneck

2023-08-27T17:35:33.064829Z

We did profiling that's how we zeroed in on that code piece

2023-08-27T17:36:35.555039Z

But that code is already after performance refactoring so it might be solved.

phronmophobic 2023-08-27T17:38:18.710059Z

The reason I ask is there are many ways to approach the problem and the solution will depend on these types of factors.

phronmophobic 2023-08-27T17:39:33.886969Z

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.

2023-08-27T17:41:35.655619Z

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).

phronmophobic 2023-08-27T17:42:57.501309Z

group-by, merge, and merge-with are not the fastest options which is why there are several alternate implementations.

2023-08-27T17:45:46.868089Z

ham looks very interesting and relevant to me, I'll try it. Thank you 🙏🏼

👍 1
2023-08-27T19:39:41.705199Z

Now I see ham only support clj (I need cljs) what a shame 😔

xificurC 2023-08-28T07:51:22.432409Z

how would the recursive case look like?