Fork me on GitHub
#specter
<
2017-11-02
>
borkdude15:11:46

Hmm, why does this print tuples instead of single values?

(setval
   [ALL
    #_(multi-path :target/source )
    :target/neighbours ALL first (fn [v]
                                   (println “is this the first?” v)
                                   v)
    (pred #{“medline”})]
   NONE
   [{:target/source “not” :target/neighbours [[“medline” 1] [“not 2”]]}
    {:target/source “medline” :target/neighbours [[“medline” 1] [“not 2"]]}
    {:target/source “medline” :target/neighbours [[“medline” 1] [“not 2”]]}
    ])

borkdude15:11:12

ALL (every map value), :target/neighbours (vector of tuples), ALL (every tuple), first … oh I see

borkdude15:11:32

first is acting as a predicate?

borkdude15:11:06

ah, FIRST, doh…

borkdude15:11:48

I have trouble writing this in specter:

;; only x and y are allowed
  [{:name "x" :rels ["x" "y"]} ;=> fine, keep as is
   {:name "y" :rels ["x" "y" "z"]} ;=> keep only allowed rels: {:name "y" :rels ["x" "y"]}
   {:name "y" :rels ["z"]} ;=> no allowed rels, remove map completely
   {:name "z" :rels ["x" "y"]}] ;=> disallowed name, remove completely
  ;;=>
  [{:name "x" :rels ["x" "y"]}
   {:name "y" :rels ["x" "y"]}]
  
as a single setval using multi-path and not-selected?. I know it must be possible…

nathanmarz15:11:23

@borkdude

(setval [ALL
         (transformed [:rels ALL (pred (complement #{"x" "y"}))] (fn [_] NONE))
         (selected?
          (multi-path
            (not-selected? :name #{"x" "y"})
            (not-selected? :rels ALL #{"x" "y"})))
         ]
  NONE
  data)

nathanmarz15:11:59

you can also do

(setval [ALL
         (transformed [:rels ALL (pred (complement #{"x" "y"}))] (fn [_] NONE))
         (selected?
          (multi-path
            (not-selected? :name #{"x" "y"})
            [:rels empty?]))
         ]
  NONE
  data)

borkdude15:11:43

cool, cool, thanks!

nathanmarz15:11:20

@borkdude looking at it again you don't need the transformed:

(setval [ALL
         (multi-path
          [:rels ALL (pred (complement #{"x" "y"}))]
          (selected?
           (multi-path
             (not-selected? :name #{"x" "y"})
             [:rels empty?])))]
  NONE
  data)

borkdude15:11:17

ah, that one makes even more sense

borkdude16:11:12

More readable too. Wasn’t familiar with transformed yet

borkdude16:11:00

Eh, wait, I didn’t know complement exists either, I always do comp not f 🙂

nathanmarz16:11:31

transformed has same semantics as view, useful when doing multiple distinct transforms in one traversal

nathanmarz16:11:22

or for manipulating the results of a select in one go

borkdude17:11:46

@nathanmarz Does this make sense? I mean the pred thing in the let. I’m not really sure when to wrap a function in pred.

(defn keep-allowed-relations [user-profile relations]
  (let [disallowed? (pred #(not (allowed-source? user-profile %)))]
    (setval
     [ALL
      (multi-path
       [:target/neighbours ALL
        (selected? FIRST
                   disallowed?)]
       (selected?
        (multi-path
         [:target/neighbours empty?]
         (selected? :target/source disallowed?)
         )))]
     NONE
     relations)))

borkdude17:11:48

but it works

borkdude17:11:14

little simplification:

(setval
     [ALL
      (multi-path
       [:target/neighbours ALL
        (selected? FIRST
                   disallowed?)]
       (selected?
        (multi-path
         [:target/neighbours empty?]
         [:target/source disallowed?]
         )))]
     NONE
     relations)))

borkdude17:11:33

This is what I meant with, it must be possible with only selected? and multi-path 🙂

borkdude17:11:03

(my data looks a little different, hence the variation with FIRST)

nathanmarz17:11:23

@borkdude that's fine though it will be slightly more efficient to use pred in the path declaration rather than outside it

nathanmarz17:11:51

that way specter knows statically it's a compiled navigator and doesn't have to do an instance? check at runtime

nathanmarz17:11:56

but that's not a big deal

nathanmarz17:11:32

wrapping with pred in the let is much better than not, in which case specter would have to do a protocol invocation to convert function -> navigator every time that callsite is invoked