specter

Latest version: 1.1.3
souenzzo 2018-08-08T14:59:40.000293Z

I need to add a item( :NEW ) before a pred ( map? ) just on first match. exaple: [:foo :bar {} {}] into [:foo :bar :NEW {} {}] I'm using mapcat and a atom to say if it's the first match. There is a simpler way to do that?

souenzzo 2018-08-08T15:07:47.000100Z

There is BEFORE-ELEM but can't understand how to compose it.

nathanmarz 2018-08-08T15:08:04.000058Z

@souenzzo you can do something like:

(defn index-matching [p]
  (fn [s]
    (select-first [INDEXED-VALS (selected? LAST (pred p)) FIRST] s)
    ))

(setval
  [(srange-dynamic (index-matching map?) (end-fn [_ i] i))
   BEFORE-ELEM]
  :NEW
  [:foo :bar {} {}]
  )

👍 1
nathanmarz 2018-08-08T15:08:41.000065Z

probably want to modify it a little to handle the case where nothing matches the predicate

jsa-aerial 2018-08-08T19:43:41.000064Z

suppose, you have a transform ALL function which makes substitutions that may themselves need to have substitutions and so reapply the transform on result until no more substitutions involved. Is the obvious soln such as (->> x (iterate xform) (drop-while (comp not test)) first) still the 'right' way to do this with specter? Or is there an even more idiomatic way?

nathanmarz 2018-08-08T19:56:25.000260Z

@jsa-aerial you could always do something like:

(def iterated-path
  (recursive-path [test] p
    (stay-then-continue
      (pred test)
      p
      )))
(transform (iterated-path #(< % 10)) inc 1)
;; => 10

jsa-aerial 2018-08-08T20:10:47.000106Z

@nathanmarz that looks very interesting - let me take a hack with that. Thanks!

jsa-aerial 2018-08-08T20:16:24.000351Z

Hmmmm, actually the test needs the last two values. Basically let x1 and x2 be the last two values, iterate until (= x1 x2).

nathanmarz 2018-08-08T20:26:54.000370Z

@jsa-aerial

(def FIXED-POINT-PATH
  (recursive-path [] p
    [(collect-one STAY)
     (multi-path
       [DISPENSE STAY]
       [(collect-one STAY)
        (if-path (collected? [a b] (= a b))
          STOP
          [DISPENSE p]
          )])
     ]))

(defn f [a] (min (inc a) 10))
(transform [:a FIXED-POINT-PATH] f {:a 1 :b 2})
;; => {:a 10 :b 2}

nathanmarz 2018-08-08T20:27:18.000170Z

that's an interesting one

nathanmarz 2018-08-08T20:28:37.000197Z

actually can shorten the definition like this:

(def FIXED-POINT-PATH
  (recursive-path [] p
    [(collect-one STAY)
     (multi-path
       [DISPENSE STAY]
       [(collect-one STAY)
        (if-path (collected? [a b] (not= a b))
          [DISPENSE p]
          )])
     ]))

nathanmarz 2018-08-08T20:30:36.000105Z

I'd probably just write that in regular clojure though

nathanmarz 2018-08-08T20:30:53.000322Z

using loop

jsa-aerial 2018-08-08T20:41:00.000319Z

I think it will be instructive to study these two - even though for the particular case in question the solution actually looks simpler in straight clojure

nathanmarz 2018-08-08T20:42:58.000187Z

for sure