This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2016-05-31
Channels
- # admin-announcements (4)
- # alda (3)
- # aws (1)
- # beginners (2)
- # boot (33)
- # braid-chat (4)
- # braveandtrue (20)
- # cider (52)
- # cljs-dev (13)
- # cljsrn (55)
- # clojure (111)
- # clojure-belgium (4)
- # clojure-brasil (6)
- # clojure-dusseldorf (1)
- # clojure-greece (116)
- # clojure-mexico (1)
- # clojure-nl (3)
- # clojure-russia (56)
- # clojure-spec (72)
- # clojure-uk (13)
- # clojurescript (66)
- # community-development (2)
- # component (24)
- # core-async (1)
- # cursive (19)
- # datomic (27)
- # devcards (5)
- # emacs (1)
- # funcool (34)
- # hoplon (313)
- # jobs (1)
- # lein-figwheel (11)
- # luminus (5)
- # mount (30)
- # off-topic (63)
- # om (375)
- # onyx (67)
- # perun (8)
- # proton (1)
- # reagent (4)
- # rum (1)
- # specter (55)
- # spirituality-ethics (7)
- # test-check (2)
- # untangled (34)
- # yada (20)
pardon my noobness, but i’m just starting out w/ specter, and i’m guessing there’s a better way to do the following that achieves better performance, and would love any guidance:
actually, here’s a simpler example where i’m still seeing my (likely non-optimal) specter code taking twice as long:
and "f3 #(reduce-kv (fn [m k v] (assoc m k (dec v))) {} %)” seems to be twice as fast as f1
ALL FIRST
and ALL LAST
seem like really common selectors, @nathanmarz what do you think about including these as KEYS
and VALS
?
or perhaps you could have another namespace that contains functions named after the ones in clojure.core
but which work as selectors
@diba @luxbock Yea the slowdown is caused by it just using generic functions to access the map as a sequence
and coercing the MapEntry's to vectors probably wasn't the right thing to do in retrospect, KEY
and VAL
selectors would be faster than coercing and using FIRST
and LAST
I'll look into using reduce-kv
for the map case of ALL
, but otherwise you can make specialized navigators to make it faster
as for having KEYS and VALS as common navigators, maybe
so far I've been hesitant to include compound navigators in the core library (since there's infinite of them possible), but I can see the argument in this case
Big release for Specter today with the new inline factoring and caching feature
No need to do manual precompilation anymore to get high performance
Also wrote up a guide to the internals of how Specter achieves high performance, recommended reading for all users: https://github.com/nathanmarz/specter/wiki/Specter-0.11.0:-Performance-without-the-tradeoffs
@nathanmarz: transform
seems to have disappeared from com.rpl.specter
in the new version
it's in the macros namespace
I recommend reading the changelog for the release as there were a few other backwards incompatible changes
I'm wanting to walk a recursive data structure composed of maps and vectors. When inside of a map I'd like to remove k-v pairs where the value matches a predicate. Can I do that with specter?
{ :a 1 :b [{:x 4 :y 3}] } ---remove where v == 4 --> {:a 1 :b [{:y 3}]}
I can easily nullify the value..seems like collect...sort-of: on the k-v pair instead of the value
@tony.kay: in that example do you mean remove x when x==4?
Oh I see remove all key/value pairs where the value matches some predicate
there's a couple ways to do it
one way is to do something like (transform [:b (collect ALL (selected? LAST #(= % 4)) FIRST)] (fn [keys m] (apply dissoc m keys)))
oh you want it to be recursive as well
one sec, I'll show you
(declarepath RecursiveMaps)
(providepath RecursiveMaps
[(walker map?)
(continue-then-stay
ALL
LAST
RecursiveMaps
)])
(transform
[RecursiveMaps
(collect ALL (selected? LAST #(= % 4)) FIRST)
]
(fn [keys m] (apply dissoc m keys))
{:a 4 :z 11 :b [{:x 4 :y 3} {:a 1}]}
)
;; => {:z 11, :b [{:y 3} {:a 1}]}
this is more advanced Specter usage, for sure
but built on the same principles
yea, my first few recursive navigations took me awhile even though I came up with this technique
now I don't even think about it
I appreciate the help. I'll read through these functions and maybe play on paper a bit
sure thing
I see select-first, and it mentions it is not more efficient....is there a way of detecting the presence of a value in a nested data structure without continuing a recursive walk?
like do a recursive search for a value matching a predicate and stop once it's reached?
you can do that for a lot of cases with com.rpl.specter.zipper
user=> (transform [z/VECTOR-ZIP (z/find-first #(and (number? %) (even? %))) z/NODE] inc [1 3 5 [2 4]])
[1 3 5 [3 4]]
the definition of find-first is pretty simple: https://github.com/nathanmarz/specter/blob/master/src/clj/com/rpl/specter/zipper.cljx#L119
oh I was just showing it for the transform case
works as you'd expect for select