Fork me on GitHub
#specter
<
2016-06-09
>
aengelberg00:06:03

@nathanmarz shall I create a github issue for the reducible traverse idea?

mac11:06:26

Do I have to do something special use specter from cljs? I have [com.rpl/specter "0.11.1"] in my build.boot (set-env! :dependencies), but my :require [com.rpl.specter :refer [select]] fails with "Referred var com.rpl.specter/select does not exist"

nathanmarz11:06:17

@mac the core select/transform/etc. operations are macros now in com.rpl.specter.macros namespace

nathanmarz11:06:40

that was a change in 0.11.0

mac11:06:43

Ah, got it.

mac11:06:23

I get a ton of warnings about "Use of undeclared Var com.rpl.specter.impl/compiled-select*" just from using select.

mac11:06:54

@nathanmarz: I just added (:require-macros [com.rpl.specter.macros :as sp]) to my namespace.

nathanmarz11:06:54

are you also requiring com.rpl.specter namespace?

mac11:06:17

nathanmarz: no, is that the issue?

mac11:06:54

nathanmarz: that fixed it 🙂

mac11:06:53

nathanmarz: thanks, specter is a fantastic piece of kit.

conaw15:06:25

@nathanmarz: when would you use continue-then-stay, vs stay-then-continue.

nathanmarz15:06:07

the first is pre-order traversal, the 2nd is post-order

nathanmarz15:06:17

in that tree example continue-then-stay would visit the leaves first

conaw15:06:52

I’m just trying to think of an example problem, and how that might affect composition

nathanmarz15:06:32

if you're changing the structure of the tree itself it can change the result

nathanmarz15:06:00

post-order that adds children will not visit the children in the same navigation, pre-order will

conaw16:06:36

Inside a recursive navigation path that was visiting every element in a tree this is irrelevant though

conaw16:06:52

I’m just trying to imagine step by step what specter is returning. Is it possible with a continue-then-stay to collect-one from all the leaves of a tree

conaw16:06:19

sort of, get the path from each leaf to the root node?

nathanmarz16:06:02

@conaw you figured out how to do it?

conaw16:06:55

well, figured out when I might use pre-order and post-order in a select I’m not totally sure how to do the transform though

conaw16:06:33

Is there a way to use setval and just set the val of a particular submap to the values collected

nathanmarz16:06:50

you need to use transform for that

nathanmarz16:06:22

setval ignores value collection

conaw16:06:00

gotcha, is it possible to use VAL or collect-one inside of continue-then-stay

conaw16:06:53

I keep getting an arity error or nil values

nathanmarz16:06:22

show me the code

conaw16:06:56

(transform [ALL (sp/continue-then-stay :children ALL (collect-one :node)) :parents] 
         (fn [& xs] (vector xs))   samplemap)

conaw16:06:10

multiple arities passed to next-fn

conaw16:06:56

or rather, wrong number of args(2) passed

nathanmarz16:06:31

that's the only known bug in specter

conaw16:06:06

continue-then-stay is a wrapper on multi-path then

nathanmarz16:06:39

same is true for any of the higher order navigators

nathanmarz16:06:41

like if-path

conaw16:06:13

Also, you mentioned at Clojure/West a few exercises that you thought were good for figuring out how to write navigators or paths well. I think you said something about nested vectors of maps. I’m trying to put together a sort of 4clojurey set of challenges for someone learning specter, if you (or anyone else in this room) have any sample problems I’d love them

aengelberg16:06:39

my favorite exercise (spoiler alert, it can only be elegantly solved with subselect) is:

;; given a vector of vectors, reverse all numbers without changing the length of any vector
in:  [[1 2 3] [4 5] [6] [7] [8 9 10]]
out: [[10 9 8] [7 6] [5] [4] [3 2 1]]

conaw16:06:59

hey that is quite elegant

nathanmarz17:06:31

here's another one: concatenate all continuous sequences of strings together

nathanmarz17:06:46

["hello" " " "word" 1 2 "a" "b" 3] -> ["hello word" 1 2 "ab" 3]

conaw17:06:49

srange-dynamic?

nathanmarz17:06:07

continuous-subseqs

nathanmarz17:06:35

adding an element to a nested set (or creating the set if it doesn't exist) without defining any new functions (anonymous or not)

nathanmarz17:06:03

{:a #{1}} -> {:a #{1 2}}

nathanmarz17:06:48

in a sequence of maps, set the :b key to true if the value for :a exists and is greater than 10

nathanmarz17:06:00

[{:a 1} {:a 11 :c 1} {:d 4}] -> [{:a 1} {:a 11 :b true :c 1} {:d 4}]

conaw17:06:34

gotta admit I’m a little stumped by what I got back from the continuous subsequence stuff

conaw17:06:21

its navigating to each character?

conaw17:06:55

(transform [(sp/continuous-subseqs string?)] str ["hello " "a " "w" 1 2 3 "a " "b" ]) [\[ \" \h \e \l \l \o \space \" \space \" \a \space \" \space \" \w \" \] 1 2 3 \[ \" \a \space \" \space \" \b \" \]]

nathanmarz17:06:30

the transform fn gets sequence in and expects sequence out

conaw17:06:52

so the challenge isn’t in the path, but in the fn you pass to transform

nathanmarz17:06:56

you're turning a vector of strings into a big string, which is then spliced back in as a sequence

nathanmarz17:06:35

yea, it's just understanding how the navigation works

conaw17:06:03

gotcha, to do this well you’d really have to do something after the transform fn

nathanmarz17:06:41

your path is right and the rest of it is making a different transform-fn

nathanmarz17:06:51

your transform-fn will be called twice, once with ["hello " "a " "w"] and once with ["a " "b"]

conaw17:06:26

Yeah, this is a good one, because I’m definitely failing to understand something about specter

conaw17:06:35

(s/def ::stringvec (s/+ (s/spec (s/+  string?))))



(defn joinup [stringvec]
  (map (partial str/join "") stringvec))


(s/fdef joinup :args ::stringvec
        :ret string?)

(s/instrument 'joinup)

(transform [(sp/continuous-subseqs string?)] joinup
            ["hello " "a " "w" 1 2 3 "a " "b" ])

conaw17:06:05

still getting back this ["hello " "a " "w" 1 2 3 "a " "b"]

conaw17:06:26

yet the spec says I’m returning a string

nathanmarz17:06:36

here i'll show you

nathanmarz17:06:52

(fn [strseq] [(apply str strseq)])

conaw17:06:15

so, because I’m not putting it in a vector at the end

conaw17:06:18

what’s happening

nathanmarz17:06:36

continuous-subseqs works just like srange

nathanmarz17:06:53

the sequence returned back replaces the subsequence navigated to

nathanmarz17:06:11

so if you just return a string back, that gets interpreted as a sequence and the individual characters get spliced in

conaw17:06:51

yeah, that’s totally obvious when you think about it

nathanmarz17:06:20

yea, you just need to visualize it

conaw17:06:53

truth, any challenges that involve navigating to a non-empty subset

nathanmarz18:06:58

I could imagine minecraft style ones

nathanmarz18:06:25

for sequence of players, if :inventory contains :flint and :stick, replace with :torch