This page is not created by, affiliated with, or supported by Slack Technologies, Inc.

## 2017-03-15

## Channels

- # arachne (6)
- # aws-lambda (3)
- # beginners (14)
- # boot (56)
- # cider (8)
- # cljs-dev (5)
- # cljsrn (11)
- # clojure (240)
- # clojure-dusseldorf (3)
- # clojure-greece (165)
- # clojure-italy (5)
- # clojure-romania (1)
- # clojure-russia (24)
- # clojure-uk (30)
- # clojure-ukraine (3)
- # clojurescript (29)
- # core-async (6)
- # css (1)
- # cursive (25)
- # datascript (6)
- # datomic (61)
- # dirac (1)
- # events (3)
- # hoplon (1)
- # instaparse (3)
- # jobs (4)
- # juxt (28)
- # lein-figwheel (7)
- # leiningen (19)
- # luminus (1)
- # lumo (2)
- # nyc (1)
- # off-topic (19)
- # om (25)
- # onyx (4)
- # parinfer (2)
- # pedestal (23)
- # perun (20)
- # re-frame (44)
- # reagent (20)
- # remote-jobs (3)
- # ring (3)
- # ring-swagger (5)
- # rum (12)
- # slack-help (3)
- # spacemacs (25)
- # specter (62)
- # sql (16)
- # unrepl (313)
- # yada (4)

I'm confused about how `continue-then-stay`

works, for example in `(continue-then-stay MAP-VALS p)`

from a recent example in this channeel.

I'm also a bit confused about `recursive-path`

, although I've used it successfully by modifying an example in the "missing piece" blog post. In `(recursive-path [] p (if-path vector? [ALL p] STAY))`

, what is `p`

bound to when it finds a vector, and why is `p`

put after `ALL`

? (Also, what's the meaning of second argument `[]`

?) `recursive-path`

seems **very** useful, but I gather it's new since it doesn't have a docstring or other documentation yet that I've found.

Apparently I don't understand how `not-selected?`

works. `(select [:a (not-selected? :c)] {:a 1 :b {:a 1 :b 2}})`

I expected to return something since :c does not exist. "Stops navigation if the path navigator finds a result. Otherwise continues with the current structure." It couldn't have found :c, so the current structure is 1, because that's what just :a gives?

@oskarkv but `:c`

always navigates to something

in this case to `nil`

if you do `(must :c)`

, that only navigates if `:c`

exists in the map

@mars0i `continue-then-stay`

does literally what it says

first it navigates to the given path

then it navigates to itself

`(transform (continue-then-stay STAY) inc 1)`

will return `3`

, because it navigates to itself, then navigates to itself again

`p`

in that example is bound to itself (aka the entire path definition given )

so for `TREE-VALUES`

, what it's saying is: if navigated at a vector, navigate to each element of the vector and recurse

otherwise (meaning not at a vector), just stay navigated at that point (finish recursing)

the `[]`

argument i used to specify arguments to the resulting path

basically the result of `recursive-path`

will be a function if any arguments are provided

@oskarkv oh just noticed you were navigating to `:a`

first, don't think that path is what you want

Thanks @nathanmarz. That's very helpful. I'm still trying to get my head wrapped around some things that aren't intuitive for me yet. I still don't understand what `p`

is doing in `if-path`

branches in `recursive-path`

. Here's an example I've been using:

```
(def a {:a1 {:b1 {:c1 1, :c2 2}, :b2 {:c1 3, :c2 4}},
:a2 {:b1 {:c1 5, :c2 6}, :b2 {:c1 7, :c2 8}}})
```

`(select [(recursive-path [] p (if-path map? [MAP-VALS p] [STAY]))] a)`

produces `[1 2 3 4 5 6 7 8]`

, i.e. the leaf node values. Why do I follow `MAP-VALS`

with `p`

? Leaving out `p`

just produces the original map wrapped in a vector, so I know I need `p`

, to get the leaf nodes, but I don't understand why. Normally, if I have a path operator like `MAP-VALS`

in a vector, it's the first navigation operation, and then the next one is applied, and so on. Here it feels as if `p`

is an argument that's passed to `MAP-VALS`

, maybe. Is that correct? So that `[MAP-VALS p]`

within `recursive-path`

(or `if-path`

?) is semantically different from, a sequence of navigators immediately after `select`

or `transform`

?

no, `p`

is just the next navigation to do after `MAP-VALS`

think of it just like regular recursion

```
(defn foo [i]
(if (= 0 i)
1
(* 2 (foo (dec i)))))
```

`foo`

refers to itself there, just like how `p`

refers to the overall path

`p`

is `(if-path map? [MAP-VALS p] [STAY]))`

the effect of using `p`

there is to continue going to all map vals until a non-map is encountered

(btw you don't need the `[]`

if it's just a single navigator)

the second branch of `if-path`

can just be `STAY`

are you comfortable with recursion with functions?

Ah, maybe I see. So `recursive-path`

doesn't in itself cause recursion to occur. It just sets up a context in which it can occur. The recursion is implemented by using the `p`

that it binds, in `if-path`

.

that's right

I see where you were confused now

`recursive-path`

does absolutely nothing except provide you with an object that references itself

`(recursive-path [] p [ALL even?])`

is the same as `[ALL even?]`

sort of

if you're curious, it's actually a wrapper around the lower level `local-declarepath`

and `providepath`

those two can be used to make mutually recursive paths

"sort of" yeah that's why I wrote "like" and "kind of" ðŸ™‚ . OK, I'll look at those at some point.

I'm not sure I understand `continue-then-stay`

followed by `p`

within `recursive-path`

, but I think I should think and experiment a bit and see if I can figure it out before asking further questions. Thanks very mush.

no problem, happy to help

Based on an answer to vikeri a week ago:

```
b ;=> {:b1 {:c1 1, :c2 2}, :b2 {:c1 3, :c2 4}}
(select [(recursive-path [] p
(if-path map?
(continue-then-stay MAP-VALS p)))
MAP-KEYS]
b)
;=> [:c1 :c2 :c1 :c2 :b1 :b2]
```

If the current element is a map, then get its vals and continue with the path, p, but also, return the current element and pass it to MAP-KEYS. So what keeps coming out of all that are the keys, and they are what are wrapped in vector. Something like that?

Or rather `MAP-VALS p`

causes `p`

into which we recurse to be bound to the outputs of `MAP-VALS`

. But also the entire map element at that point is passed to `MAP-KEYS`

.

better to think of it one step at a time

@mars0i the `recursive-path`

part navigates to all maps reachable via navigations to map vals

then for each map navigated to, it navigates to the keys

because of the `continue-then-stay`

, transformations happen first on more descendant maps

whereas with `stay-then-continue`

the opposite would be true

worth looking at their implementations https://github.com/nathanmarz/specter/blob/master/src/clj/com/rpl/specter.cljc#L1204

thin wrappers around `multi-path`