specter

Latest version: 1.1.3
twashing 2019-01-25T10:18:38.046900Z

I have a set of nested records. In my structure, I want to STAY on the i. the value nodes with :bar keys, that are ii. not seqable? and iii. not of type myns.Foo. But I can’t seem to get the recursive navigator correctly. Any ideas here?

(def a #myns.Foo{:bar #myns.Foo{:bar (#myns.Foo{:bar :a :x 1 :y 2} :b :c :d)}})

(def b (recursive-path
         [] p
         (cond-path
           seqable? [ALL p]
           [:matcher (comp clojure.core/not parser-combinator?)] (continue-then-stay ALL p)
           [:matcher (comp clojure.core/not seqable?)] [ALL p])))

(select b a)

nathanmarz 2019-01-25T15:23:56.047900Z

@twashing it would be more clear if you showed desired input and output

twashing 2019-01-25T21:43:55.048400Z

Hey @nathanmarz, absolutely. So I’m trying to find the recursive-path that gives me the output in *B, given the input from A*.

twashing 2019-01-25T21:43:56.048600Z

;; A input structure
(defrecord Foo [bar])
(def a #user.Foo{:bar #user.Foo{:bar '(#user.Foo{:bar :a :x 1 :y 2} :b :c :d)}})

;; B output 
:a ;; (the i. the value nodes with :bar keys, that are ii. not seqable? and iii. not of type myns.Foo)

nathanmarz 2019-01-25T22:30:37.049Z

@twashing is this what you're looking for?

(def MY-WALKER
  (recursive-path [] p
    (cond-path
      #(instance? Foo %) [:bar p]
      seqable? [ALL #(instance? Foo %) p]
      STAY STAY
      )))

twashing 2019-01-25T22:38:39.049300Z

@nathanmarz Hmm, if I put this into my repl, I get an empty result set.

twashing 2019-01-25T22:39:08.049800Z

(use 'com.rpl.specter)

(defrecord Foo [bar])

(def a #user.Foo{:bar #user.Foo{:bar '(#user.Foo{:bar :a :x 1 :y 2} :b :c :d)}})

(def MY-WALKER
  (recursive-path [] p
    (cond-path
      #(instance? Foo %) [:bar p]
      seqable? [ALL #(instance? Foo %) p]
      STAY STAY)))

(select MY-WALKER a)

;; [] - empty result set returned

twashing 2019-01-25T22:39:19.050Z

It’s a tricky one.

nathanmarz 2019-01-25T23:00:36.050400Z

@twashing probably because you meant to do (def a #user.Foo{:bar #user.Foo{:bar (#user.Foo{:bar :a :x 1 :y 2} :b :c :d)}}) ?

twashing 2019-01-25T23:06:26.051400Z

Ah ok.

twashing 2019-01-25T23:06:51.052Z

Didn’t realise the reader macro stopped the list from being eval’d… Cool.

twashing 2019-01-25T23:09:27.052800Z

Cheers mate. I think I have a better understanding of the semantics of if-path and cond-path.

twashing 2019-01-25T23:10:59.053900Z

Although STAY STAY (to capture the leaves) is still a bit foggy.. used as both a predicate and navigator.

twashing 2019-01-25T23:11:12.054200Z

Thanks for a great library!

nathanmarz 2019-01-25T23:34:35.054700Z

@twashing An if-path/`cond-path` condition is "true" if it navigates to at least one value

nathanmarz 2019-01-25T23:34:43.055Z

so STAY is the navigation equivalent of true

twashing 2019-01-25T23:36:05.055400Z

Gotcha :thumbsup::skin-tone-5: