Fork me on GitHub
#specter
<
2017-03-17
>
oskarkv14:03:59

What is this in (defnav a [x] (select* [this structure next-fn] ...)) I tried to use it but "Unable to resolve symbol this".

mars0i15:03:46

Looks like it's being used inside a proxy def @oskarkv

mars0i15:03:00

ie is that where that code originated?

nathanmarz15:03:43

@oskarkv that's currently ignored

nathanmarz15:03:59

just there for consistency with how method definition works in clojure

nathanmarz15:03:51

if you use defrichnav, then this refers to the navigator object

levitanong17:03:35

hi would transformed be able to receive a value from above its scope? Like:

(transform
  [VAL
   (transformed
     [some-path]
     (fn [value-from-VAL path-from-transformed]
       (do-something)))]
  (fn [value-from-VAL value-from-transformed]
    (do-another-thing)))

nathanmarz17:03:36

@levitanong no, I opted to design it so the values for transformed are reset

levitanong17:03:31

@nathanmarz So if within a transform I use a transformed followed by some navigator, the “cursor” that navigator will operate on will be the original shape of the data passed to transform?

levitanong17:03:45

i.e. as if i had used a collector

levitanong17:03:51

without any collecting going on

nathanmarz17:03:53

no, it just ignores collected values

nathanmarz17:03:09

(transform [ALL (transformed STAY inc)] inc [1 2 3 4]) will emit [3 4 5 6]

levitanong17:03:52

I think i have to parse this. lol

levitanong17:03:58

thanks for the replies, @nathanmarz

levitanong17:03:54

(transform [(transformed [VAL :key ALL] (fn [a b] (inc b)) VAL even?] 
  (fn [a b] (println a))
  {:key [1 2 3 4]})
In this above example, I expect a to be [2 3 4 5], but I seem to be getting {:key [2 3 4 5]} At least, this is a simplified version of what I’m trying to do. Is this expected behavior?

nathanmarz18:03:49

@levitanong that code produces an error

nathanmarz18:03:06

since it's trying to incrementing a vector in the transformed clause

nathanmarz18:03:55

now because it's calling even? on the map

nathanmarz18:03:58

but anyway, the navigator after the transformed clause will get {:key [2 3 4 5]} as input

levitanong18:03:25

@nathanmarz so it doesn’t actually navigate to the transformed values

nathanmarz18:03:42

it works just like view

levitanong18:03:22

oh, must’ve misread the docs on transformed

levitanong18:03:45

i was almost certain it said “navigates to the transformed values” or somesuch.

levitanong18:03:57

Anyway, thanks! I am no longer confused 😄

mars0i19:03:35

I've been trying to use Specter to return paths of keys from embedded maps. e.g. amalloy's answer at http://stackoverflow.com/questions/21768802/how-can-i-get-the-nested-keys-of-a-map-in-clojure :

mars0i19:03:20

(defn keys-in [m]
  (if (or (not (map? m))
          (empty? m))
    '(())
    (for [[k v] m
          subkey (keys-in v)]
      (cons k subkey))))

mars0i19:03:27

(keys-in {:a1 {:b1 {:c1 1, :c2 2}, :b2 {:c2 3}}, :a2 {:b2 {:c1 4, :c2 5}}})

mars0i19:03:41

;=> ((:a1 :b1 :c1) (:a1 :b1 :c2) (:a1 :b2 :c2) (:a2 :b2 :c1) (:a2 :b2 :c2))

mars0i19:03:28

I have been trying everything, turning myself inside-out. Probably used combinations of half of the items on the navigators page.

mars0i19:03:54

Found out about transformed from above discussion, thought that was the key. Argh.

mars0i19:03:37

Is this possible in Specter? Undoubtedly yes. Is it possible more simply than without it, though? I suspect so, but I don't yet have the insight to see how.

mars0i19:03:11

Actually I don't need amalloy's empty? test. Just testing for map? is enough.

nathanmarz19:03:02

@mars0i you can do that with value collection

mars0i19:03:10

I have experimented with VAL, collect, collect-one, but haven't figured out the magic configuration.

nathanmarz19:03:29

(defn keys-in [m]
  (let [p (recursive-path [] p
            (if-path map?
              [ALL (collect-one FIRST) LAST p]
              STAY
              ))]
    (map butlast (select p m))
    ))

nathanmarz19:03:33

that's one way

mars0i19:03:42

Beautiful. Thanks. I'll digest that now.

nathanmarz19:03:44

here's another way:

(defn keys-in [m]
  (let [p (recursive-path [] p
            (if-path map?
              [ALL
               (if-path [LAST map?]
                [(collect-one FIRST) LAST p]
                FIRST
                )]))]
    (select p m)
    ))

nathanmarz19:03:49

more efficient

mars0i19:03:53

I'd like to have this added to that StackOverflow question. I'll do it and credit you, if you want, but if you play SO and have time, you could get the points.

mars0i19:03:00

Great. more to digest ...

mars0i19:03:45

OK, thanks much. I think there ought to be a Specter solution there. I'll add both. I saw a discussion elsewhere someone trying to do this with Specter and gave up.

nathanmarz20:03:24

once your brain adapts to thinking in terms of navigation this is easy stuff

mars0i20:03:32

I believe that. Still getting there.

mars0i20:03:45

i.e. the discussion elsewhere someone else gave up. So it's not just me who thought of using Specter for this kind of thing.

nathanmarz20:03:53

@mars0i also worth noting that the specter solution should be significantly more efficient than all the solutions on that page

nathanmarz20:03:58

except for the amalloy one which is probably comparable

mars0i21:03:26

I was wondering about that. I'll run the specter defs through Criterium later. I'm using very small structures, so differences might not show up.

mars0i21:03:24

At some point I might randomly generate some large embedded maps just to see how the algorithms perform, but I don't have a need for large ones.

nathanmarz21:03:02

@mars0i you should see a substantial difference