Fork me on GitHub
#specter
<
2016-06-11
>
luxbock10:06:47

how can I move lift the filter-part from the function into the selector?

conaw10:06:08

filterer?

luxbock10:06:06

@conaw: I think that counts the :bar keys as well

luxbock10:06:12

the return value I want is {:a 2, :b 3}

codonnell11:06:47

@luxbock: not sure if this is optimal, but it works

codonnell11:06:51

(transform [MAP-VALS (collect-one (filterer (fn [m] (contains? m :foo))))] (fn [ms _] (count ms)) data)

nathanmarz11:06:26

@luxbock: I would do it like this:

(transform [MAP-VALS (collect ALL (pred :foo))]
  (fn [a _] (count a))
  {:a [{:foo 1} {:bar 3} {:foo 4}]
   :b [{:foo 1} {:bar 3 :foo 4} {:foo 4}]}
  )

nathanmarz11:06:09

can also use must instead of pred for contains? semantics

codonnell12:06:38

I'm trying to understand how late binding works for filterer. It seems to work fine if I pass it a late binding navigator, like must or pred. However, if I try to pass a predicate function directly, I get an exception. Is that just how filterer works or am I missing something?

nathanmarz12:06:52

@codonnell: filterer isn't a navigator

nathanmarz12:06:00

it's a function that returns a navigator

nathanmarz12:06:28

so when you use it in comp-path it gets interpreted like all functions do – as a filter function

nathanmarz12:06:11

filterer can be invoked with a path that requires more parameters to then create a navigator that requires those parameters

nathanmarz12:06:37

btw, it's very rare that you need to explicitly precompile anymore

nathanmarz12:06:19

(select-one (filterer even?) (range 10)) in 0.11.2 should be within 2-3% of the precompiled code

codonnell12:06:52

Alright, that makes sense. Thanks for the response. I'm aware that compiling paths is generally unnecessary in 0.11.2. I'm writing up some notes for myself and got confused about filterer behavior, so I wanted to clarify for my notes.

nathanmarz12:06:27

Specter should detect that mistake and throw an error

codonnell12:06:58

I appreciate that. Informative error messages make a huge difference.

conaw12:06:10

is there a reason why MAP-VALS might not work in cljs

conaw12:06:28

Use of undeclared Var com.rpl.specter/MAP-VALS at line 1

conaw12:06:28

easy enough to define oneself, but surprised by that error

nathanmarz12:06:50

Are you using 0.11.1 or later?

nathanmarz12:06:16

you should use the built-in one as its about twice as fast at [ALL LAST]

nathanmarz12:06:25

it was added in 0.11.1

nathanmarz12:06:38

Highly recommend upgrading to 0.11.2

conaw13:06:37

@nathanmarz: regarding @luxbock’s example, when I do

(transform [ALL LAST (sp/collect ALL (sp/pred :foo))]
        count
    {:a [{:foo 1} {:bar 3} {:foo 4}]
     :c [{:foo 1} {:bar 3 :foo 4} {:foo 4}]})

;;=>  {:a 2 c: 3}

(transform [MAP-VALS (sp/collect ALL (sp/pred :foo))]
           (fn [e _] (count e))
           {:a [{:foo 1} {:bar 3} {:foo 4}]
            :c [{:foo 1} {:bar 3 :foo 4} {:foo 4}]})
;;=> 0

conaw13:06:27

(transform [MAP-VALS (sp/collect ALL (sp/pred :foo))]
           count
           {:a [{:foo 1} {:bar 3} {:foo 4}]
     :b [{:foo 1} {:bar 3 :foo 4} {:foo 4}]})
;;=> 0

codonnell13:06:36

(transform [MAP-VALS (collect ALL (must :foo))] (fn [c _] (count c)) data)
{:a 2, :b 3}

conaw13:06:13

I’m just pointing out that ALL LAST and MAP-VALS aren’t equivalent in this case

codonnell13:06:20

ah, interesting

conaw13:06:47

pred and must are equivelent

conaw13:06:18

(transform [ALL LAST (sp/collect ALL (sp/must :foo))]
        count
    {:a [{:foo 1} {:bar 3} {:foo 4}]
     :b [{:foo 1} {:bar 3 :foo 4} {:foo 4}]})
;;=> {:a 2 :b 3}

conaw13:06:51

in this example at least

nathanmarz13:06:51

@conaw: not reproducing your [ALL LAST] vs. MAP-VALS

codonnell13:06:22

I'm not sure how those are working with plain count. Shouldn't the transforming function get passed two values?

codonnell13:06:39

I get an exception that count is passed two values.

nathanmarz13:06:00

it shouldn't be working but it looks like clojurescript doesn't throw an arity exception

nathanmarz13:06:08

it just ignores args beyond the first

conaw13:06:44

either way, why would I be getting 0 back from the map vals transform

conaw13:06:02

this is the exact code I’m running

(transform [ALL LAST (collect ALL (must :foo))]
        count
    {:a [{:foo 1} {:bar 3} {:foo 4}]
     :b [{:foo 1} {:bar 3 :foo 4} {:foo 4}]})


(transform [MAP-VALS (sp/collect ALL (pred :foo))]
           (fn [a _] (count a))
           {:a [{:foo 1} {:bar 3} {:foo 4}]
            :b [{:foo 1} {:bar 3 :foo 4} {:foo 4}]})

conaw13:06:12

using specter 0.11.2

conaw13:06:57

(transform [ALL LAST (collect ALL (must :foo))]
        (fn [a _] (count a))
    {:a [{:foo 1} {:bar 3} {:foo 4}]
     :b [{:foo 1} {:bar 3 :foo 4} {:foo 4}]})

conaw13:06:03

this also returns expected value

conaw13:06:11

just MAP-VALS that doesn't

nathanmarz13:06:21

cljs.user=> 
(transform [s/MAP-VALS (s/collect s/ALL (s/pred :foo))]
           (fn [a _] (count a))
           {:a [{:foo 1} {:bar 3} {:foo 4}]
            :b [{:foo 1} {:bar 3 :foo 4} {:foo 4}]})
{:a 2, :b 3}

nathanmarz13:06:44

cljs.user=> 
(transform [s/MAP-VALS (s/collect s/ALL (s/must :foo))]
           (fn [a _] (count a))
           {:a [{:foo 1} {:bar 3} {:foo 4}]
            :b [{:foo 1} {:bar 3 :foo 4} {:foo 4}]})
{:a 2, :b 3}

conaw13:06:27

yeah, that’s what I’m running

conaw13:06:29

getting 0

nathanmarz13:06:37

are you redefining MAP-VALS?

nathanmarz13:06:03

are you doing it from a fresh repl?

conaw13:06:10

just did a lein clean

conaw13:06:14

and started repl fresh

nathanmarz13:06:44

(require '[com.rpl.specter :as s])
(require-macros '[com.rpl.specter.macros :refer [select transform]])

(transform [s/MAP-VALS (s/collect s/ALL (s/pred :foo))]
           (fn [a _] (count a))
           {:a [{:foo 1} {:bar 3} {:foo 4}]
            :b [{:foo 1} {:bar 3 :foo 4} {:foo 4}]})

nathanmarz13:06:50

and that exact code returns 0?

nathanmarz13:06:56

doesn't make any sense

nathanmarz13:06:09

you'll need to put up a repo and instructions to reproduce it

nathanmarz13:06:46

oh one more idea

nathanmarz13:06:49

what version of cljs?

conaw13:06:09

I’ve been using specter and spec together

nathanmarz13:06:04

what version of clojure are you pairing that with?

nathanmarz13:06:09

1.9.0-alpha4?

conaw13:06:29

are you on more recent?

nathanmarz13:06:28

i just tried on those exact versions and it works fine

nathanmarz13:06:35

so yea, need a repo to see what's going on

luxbock14:06:31

thanks @nathanmarz

conaw14:06:50

@luxbock: map-vals works fine for you right?

luxbock14:06:40

@conaw, I need to upgrade to check

conaw14:06:02

@nathanmarz: must be something on my end, created a new clean project and got it working fine

conaw14:06:01

this is what I get back from (transform MAP-VALS inc {:a 1 :b 2})

"{:a 1, :b 2}1”

conaw14:06:46

I’m getting that in a file where the ONLY thing I’m loading in is specter

conaw14:06:55

and the only function is that

conaw14:06:55

also strange that this is the only part of specter that’s giving me weird results

luxbock15:06:03

ah yeah works fine for me

codonnell22:06:51

Does anyone know how subselect is meant to be used?

eraserhd22:06:22

I’ve just published a library that has specter paths for working with formatted EDN and clojure code: https://github.com/maitria/specter-edn

eraserhd22:06:54

It navigates to parsed S-expressions, but re-inserts whitespace and comments.

nathanmarz23:06:02

@codonnell: subselect navigates you to the elements in the given path and lets you manipulate them as a sequence, but transformations will be applied back at the original locations

nathanmarz23:06:26

(transform (subselect (walker number?) even?)
  reverse
  [1 [[[2]] 3] 5 [6 [7 8]] 10])
;; => [1 [[[10]] 3] 5 [8 [7 6]] 2]

nathanmarz23:06:09

@eraserhd: very cool!