Fork me on GitHub
#specter
<
2017-04-19
>
Al Baker00:04:31

is there a way to walk any arbitrary map/vector/map nested structure?

Al Baker00:04:04

trying to get success generations of something like {:a "blah" :b :undefined} -> {:a blah :b [{:a "blah :b :undefined}] }

nathanmarz02:04:23

@albaker yes, walker does that

nathanmarz02:04:48

or you can define a more precise navigator using recursive-path

nathanmarz02:04:08

not sure what you're going for with that transformation, need more examples or explanation

mbjarland04:04:28

@nathanmarz thank you. Got the select part right while tinkering last night, should have seen the view function pattern, guidance much appreciated.

mbjarland09:04:28

@nathanmarz is there any way to refer back to a collect-one:ed value in a filter expression later in the path?

nathanmarz11:04:33

@mbjarland yes, use collected?

nathanmarz11:04:58

also see DISPENSE and with-fresh-collected

mbjarland11:04:28

@nathanmarz fresh out the oven? these don't seem to be part of the online docs, will fire up a repl and take a look

Al Baker13:04:42

@nathanmarz basically want to run something like (transform walker expander-function) that I can repeatedly call until some notion of completion

Al Baker13:04:20

where each transform has that {:a "blah" :b :undefined} -> {:a blah :b [{:a "blah :b :undefined}] } style replace a key in the map, or maybe nested map/vectors

nathanmarz14:04:14

@albaker you can use stay-then-continue to transform something and then continue recursing into the transformed value

nathanmarz14:04:04

e.g. (recursive-path [] p [(walker vector?) (stay-then-continue ALL p)])

Al Baker14:04:42

but that'll walk vectors or also maps/vectors of maps, with vectors of maps, etc

nathanmarz14:04:06

that will walk all clojure data structures until it reaches a vector, then it will do the transformation and continue walking

nathanmarz14:04:21

if you want different behavior then you can encode that into your recursive path definition

Al Baker14:04:08

so walker wants a predicate function that returns truthy for something you want to process

Al Baker14:04:20

ok cool, I'll give that a whirl

mbjarland14:04:09

@nathanmarz if I am on a node which is a map and want to do a calculation on the values for two keys on that map, i.e.

(view #(- (read-string (:to %)) (read-string (:from %))))
it seems that % does not evaluate to the current node in the above expression?

mbjarland14:04:26

take that back, figured it out, my bad

Al Baker15:04:50

@nathanmarz so that works so well, I'm stack overflowing as the descent into the tree (or madness?) goes.. in this case, making a graph query to find more children until no more children can be had. Are there any gotchas (other then don't do that) to avoid in the transform?

Al Baker15:04:02

I guess I could move the query into a core.async channel, so transform is just pulling from channels

nathanmarz15:04:49

@albaker specter doesn't use any more stack than you would expect

nathanmarz15:04:10

each level in data structure you go down during the transform will be another stack frame

Al Baker15:04:36

yeah I suspect it's in the db client somewhere

nathanmarz15:04:02

don't know enough about your use case to give any guidance beyond that

Al Baker15:04:05

I'll move the db client behind a core.async queue and leaves the transforming function only doing a quick put a thing on, get a thing back transaction and lets the db query run separately

Al Baker15:04:35

don't feel like playing the "why I hate Apache HTTP commons today" game on why it's stack overflowing 😄

lvh22:04:04

Does anyone have any suggestions for a faster clojure.data/diff? I don’t know if anyone’s e.g. tried specter for this (or if it’d even help). I imagine zippers might, at least. I currently have two mostly-similar nested trees (flattened about 2E5 entries) and clojure.data/diff just takes a very long time

lvh22:04:46

I dunno if it matters, but the two data structures are very similar, deeply nested, and form a deep (as opposed to broad) tree