Fork me on GitHub
#specter
<
2017-01-10
>
richiardiandrea00:01:13

maybe FAQ πŸ™‚ is there a way in specter to stop to the first MAP-VALS, without further going deep in a map for instance?

qqq00:01:20

is there a way to avoid the all caps? On a kinesis advantage pro keyboard, typing all caps is quite annoying

nathanmarz00:01:54

@qqq you can do (def my-all ALL) if you want

qqq00:01:15

yeah, I my have to

qqq00:01:22

MAP_VALS is really awkward on the kinesis

qqq00:01:46

I guess you can't use :all or :map-vals since you're using kws for kw selector functions

nathanmarz00:01:36

keywords extend ImplicitNav in order to wrap themselves in keypath

nathanmarz00:01:02

@richiardiandrea fyi, there are some ideas about supporting that in the future though: https://github.com/nathanmarz/specter/issues/125

richiardiandrea00:01:55

oh cool, for a moment I though I could use STOP for it

richiardiandrea00:01:43

btw I tried 0.13.3-SNAPSHOT and the NONE syntax works here, but because it navigates deeply in the data, it is still something different from what I was thinking

nathanmarz00:01:10

what do you mean?

richiardiandrea00:01:42

uhm...no ok I lost it, I tried another example but it works fine, give a couple of minutes πŸ˜„

richiardiandrea00:01:56

uhm (2), I tried again what I had in mind and it works fine...

richiardiandrea00:01:09

It was (sp/setval [sp/MAP-VALS #(map? %)] sp/NONE {:a 3 :b 5 :c {:d 5}})

richiardiandrea00:01:13

very convenient btw πŸ‘

richiardiandrea01:01:20

@nathanmarz every time I turn to Specter for data manipulation, I surprise myself with the simplicity of the result, thanks:

(sp/transform [(sp/collect-one [:family (sp/submap [:name :description])])
                                             :family
                                             (sp/submap [:resource :relationship])
                                             sp/MAP-VALS
                                             sp/ALL]
                                            (fn [family m]
                                              (assoc m :family family)) 
                                 (first families))

richiardiandrea01:01:35

the collect feature is super neat

nathanmarz01:01:39

yea I use that feature quite a bit

richiardiandrea01:01:18

I wanted basically to avoid using a submap with keys there

richiardiandrea01:01:53

so that I can assoc to all the key-values where the value is a map

richiardiandrea01:01:12

oh ok wow done πŸ˜‰

richiardiandrea01:01:10

(defn propagate-family
  [family]
  (sp/transform [(sp/collect-one [:family (sp/submap [:name :description])])
                 :family
                 sp/MAP-VALS
                 #(vector? %)
                 sp/ALL]
                (fn [family m]
                  (assoc m :family family))
                family))

bfabry03:01:09

omg people use like my only oss contribution ever, goosebumps πŸ˜„

qqq03:01:18

http://stackoverflow.com/questions/39123457/how-to-use-specter-in-clojurescript <-- is using specter in cljs in figwheel still a problem? (I'm having problems using specter in cljs, but not in clj, and I can't figure out why)

nathanmarz03:01:48

@qqq I've only used it in Node myself

nathanmarz03:01:33

what specific problem are you having?

nathanmarz03:01:03

@richiardiandrea fyi you can write that in a simpler way like this:

(defn propagate-family
  [family]
  (sp/transform [:family
                 (sp/collect-one (sp/submap [:name :description]))
                 sp/MAP-VALS
                 vector?
                 sp/ALL
                 :family]
                (fn [family _] family)
                family))

richiardiandrea04:01:19

Thanks @nathanmarz, is transform acting like update then?

richiardiandrea04:01:56

Did not know that, even better πŸ˜„

qqq04:01:47

@nathanmarz: let me create a minimal failure care

qqq04:01:40

false alarm, I was requiring com.rpl/specter instead of com.rpl/specter

nathanmarz04:01:14

@richiardiandrea yea it's like update on steroids

qqq04:01:53

@nathanmarz : from a newcomer perspective, it might help if at the very top of the README.md, there was a line to the effect of transform takes two functions, one to select items, one to update, and leaves everything else the samespe

nathanmarz04:01:11

yea the documentation could be a lot better

nathanmarz04:01:46

a good beginner tutorial would be great, but I don't have time for that now

nathanmarz04:01:55

would love documentation contributions

richiardiandrea20:01:59

@nathanmarz is there a more elegant way to do this:

(defn normalize-family
  [family]
  (merge
   (sp/setval [sp/MAP-VALS string?] sp/NONE (:family family))
   (sp/transform [(sp/collect-one [:family (sp/submap [:name :description])])
                  :family]
                 (fn [family _] family)
                 family)))

richiardiandrea20:01:55

the initial shape is {:family {:name "art" :desc "sda" :complex-map {....}}

richiardiandrea20:01:25

and I basically want to transform it into {:family {:name "art" :desc "sda"} :complex-map {....}}

nathanmarz20:01:39

you just want to move :complex-map keypair into parent map?

richiardiandrea20:01:55

ah yes that's another way to see it πŸ˜„

richiardiandrea20:01:30

but all the :complex-maps, so everything that has not a string? value should go up

nathanmarz20:01:19

I think the way you're doing it is fine

qqq20:01:23

in specter, is it possible for a update function to depend not only on the value, but also on the "path" down to the node ?

richiardiandrea20:01:49

@qqq I think there is a https://github.com/nathanmarz/specter/wiki/List-of-Navigators#if-path but I guess depends a lot on what you have in mind

bfabry20:01:31

@qqq have you got a pseudo example?

qqq20:01:08

{:a {:b [:apple :orange :pear]
     :c [:juice]}
 :e [:cat :dog]}

to

{:a {:b [[[:a :b 0] :apple]
         [[:a :b 1] :orange]
         [[:a :b 2] :pear]]
     :c [[[:a :c 0] :juice]]}
 :e [[[:e 0] :cat]
     [[:e 1] :dog]
     ]}
^^ can specter do the above transform ? I want to map over the leafs, and for each leaf, also store into it its 'path'

bfabry20:01:58

that's an interesting thought. what would you want to receive if it went through a navigator like a predicate? #(.startsWith % ":or") or similar?

qqq21:01:19

I never considered that case.

qqq21:01:37

Maybe this is not a right fit with specter, since specter is "does more than indexing"

qqq21:01:48

In haskell, this is trivial with a "reader monad"

qqq21:01:55

not sure the right clojure solution

bfabry21:01:38

maybe zippers if your data is representable as a tree (which that is)

nathanmarz21:01:13

@qqq you can collect values as you go

qqq21:01:50

nathanmarz: does this involve (1) making the 'update' function impure', or (2) does specter support the reader monad?

nathanmarz21:01:46

@qqq like this:

(defnav ALL-INDEXED []
  (select* [this structure next-fn]
    ;; fill this in
    )
  (transform* [this structure next-fn]
    (map-indexed
      (fn [i v]
        (second (next-fn [i v])))
      structure
      )))


(def MyPath
  (recursive-path [] p
    (cond-path map? [ALL (collect-one FIRST) LAST p]
               vector? [ALL-INDEXED (collect-one FIRST) LAST p]
               STAY STAY)))

(transform MyPath
  (fn [& vals] vals)
  {:a {:b [:apple :orange :pear]
   :c [:juice]}
   :e [:cat :dog]})

nathanmarz21:01:15

more work is needed on ALL-INDEXED to make it preserve type (ala ALL), but that's the gist of it

schmee21:01:25

(removed redudant answer cause slack was out of sync)

schmee22:01:21

if I have a path like this, will it get cached automatically?

schmee22:01:24

(defn every-nth [n] [ALL-INDEXED (collect-one FIRST) (fn [[i _]] (= 0 (mod i n))) LAST])

schmee22:01:39

using your implementation of ALL-INDEXED above

nathanmarz22:01:52

just do this:

(defn every-nth [n] (path ALL-INDEXED (collect-one FIRST) (fn [[i _]] (= 0 (mod i n))) LAST))

schmee22:01:19

ahh, gotcha

nathanmarz22:01:32

path implements all the inline caching stuff

schmee22:01:17

also, the macros wiki page mentioned a must-cache-paths! fn, but it seems like that function is gone?

nathanmarz22:01:38

yea that's gone as of 0.13.0

nathanmarz22:01:59

every path can be inline cached now

schmee22:01:42

sweet πŸ‘

schmee22:01:40

it’s really a whole new paradigm to use Specter, I feel kinda lost just like I did when I went from imperative to functional programming

schmee22:01:49

but I guess it will reveal itself in due time πŸ™‚

nathanmarz22:01:32

you'll get there

nathanmarz22:01:39

eventually you'll wonder how you ever programmed without it