Fork me on GitHub
#specter
<
2017-03-03
>
james07:03:36

@nathanmarz Congratulations on the 1.0 release! Specter is an amazing feat of software engineering, and an essential part of my Clojure toolbox. Thank you so much for turning my least favourite part of Clojure (manipulating nested data structures) from a frustrating slog into joyful productivity!

bill_tozier13:03:28

I’ve been able to replicate all the examples involving trees, of course. The bigger picture for me, though, is to be able to select a random item from a tree and transform that. Working it out with a zipper is simple enough, but I was hoping to produce a clearer and more readable function that uses Specter. I’m working through from the given examples “change every X in a tree to Y”, and I’ve got a working version in which one of the filters is a random function. So I can now change a random subset of the nodes in a tree to new values. But selecting only one of those is turning out to be problematic for me. Maybe if I could find the source for the FIRST and LAST navigators? ¯\(ツ)

nathanmarz13:03:55

@bill_tozier FIRST/`LAST` navigate you to the first or last element of a sequence

bill_tozier13:03:36

That was my guess, yes.

nathanmarz13:03:48

if you want to change a random element, you'll first need:

(def TREE-VALUES
  (recursive-path [] p
    (if-path vector?
      [ALL p]
      STAY)))

nathanmarz13:03:48

Then do (transform (subselect TREE-VALUES) (fn [all-vals] ...) tree)

nathanmarz13:03:13

and inside your custom function change a random element of that sequence

nathanmarz13:03:57

you could also use define a custom navigator for it though it's tricky since it's better if navigators are deterministic (so they work with subselect, for instance)

nathanmarz13:03:27

your custom navigator would need to generate a random seed, and then always use that seed to navigate to the same random element

nathanmarz13:03:06

so usage would probably be something like: (setval [(subselect TREE-VALUES) (random-elem)] 1111 tree)

bill_tozier14:03:54

nathanmarz: Thanks! I had made the mistake of thinking a navigator accumulated a collection of paths to items. I realize that’s the un-lazy inefficient way, which is how I got sidetracked.

val_waeselynck13:03:44

I seem unable to use setval NONE to dissoc fro a map, any idea why ?

val_waeselynck13:03:46

(setval [:a :b :c] NONE {:a {:b {:c 1}}})
=> {:a {:b {:c :com.rpl.specter.impl/NONE}}}

val_waeselynck13:03:24

This is weird as I'm using specter 1.0.0

schmee14:03:18

val_waeselynck are you sure?

schmee14:03:34

I get this:

user=> (setval [:a :b :c] NONE {:a {:b {:c 1}}})
{:a {:b {}}}

val_waeselynck14:03:03

maybe I have some classpath issue I don't understand, but I don't know how to find out...

val_waeselynck14:03:15

$ lein deps :tree | grep specter yields

val_waeselynck14:03:19

[com.rpl/specter "1.0.0"]

schmee14:03:41

:thinking_face:

schmee14:03:04

have you tried restarting the repl?

schmee14:03:14

the catch-all solution 😛

val_waeselynck14:03:59

trying again after a lein clean ...

val_waeselynck14:03:08

see you in 2 minutes ^^

val_waeselynck14:03:02

OK, it does work, awesome