This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2016-06-10
Channels
- # admin-announcements (2)
- # arachne (2)
- # beginners (53)
- # boot (52)
- # cider (7)
- # cljs-dev (61)
- # cljsrn (12)
- # clojure (61)
- # clojure-greece (22)
- # clojure-nl (16)
- # clojure-russia (103)
- # clojure-spec (84)
- # clojure-uk (15)
- # clojurescript (137)
- # community-development (14)
- # cursive (4)
- # datomic (14)
- # devcards (6)
- # euroclojure (3)
- # funcool (26)
- # hoplon (27)
- # jobs (4)
- # lambdaisland (1)
- # leiningen (1)
- # om (75)
- # onyx (77)
- # planck (15)
- # proton (2)
- # re-frame (23)
- # ring-swagger (9)
- # schema (1)
- # specter (95)
- # untangled (124)
- # yada (27)
Alright, here’s another challenge. Let me know if this is just taking the idea of everything as a navigation too far though. Given this [[1 2] [1 3] [3 4] [4 5] [5 6]]
I mean, you can
but it's not particularly better than the manual code since everything in the structure is used
(require '[clojure.set :as set])
(defnav MERGED-MAPS []
(select* [this structure next-fn]
;;TODO: fill this in
)
(transform* [this structure next-fn]
(apply merge-with (fn [& vals] (next-fn vals)) structure)
))
(transform
[(parser #(transform ALL (fn [[k v]] {k #{v}}) %) #(vec %))
MERGED-MAPS]
#(apply set/union %)
[[1 2] [1 3] [3 4] [4 5] [5 6]])
that outputs [[1 #{3 2}] [3 #{4}] [4 #{5}] [5 #{6}]]
@conaw It's most commonly used for something like this:
(def LONG-PARSER (parser #(Long/parseLong %) str))
(transform [ALL LONG-PARSER] inc ["10" "1" "0"])
;; => ["11" "2" "1"]
the docs are very incomplete, though most of the public API has docstrings
ok, here’s a question. Is there a way I could do a transform that would be akin to map-indexed. (transform [TOPSORT :position-id (subset #{})] (fn [x] something that gives me an unique value in the range of zero to the number of items I’m doing the select on) tree)
the function for transform is only getting access to one selected value at a time right
so you’d have to do something like, pass the whole subsequence of values you want as a sequence, and then put them all back in in the right place
I think you're looking for subselect
(transform (subselect ALL even?) reverse [1 2 3 4 5 6 7])
-> [1 6 3 4 5 2 7]
(transform [(sp/subselect ALL map? :position)] (partial map-indexed (fn [i x] i)) [{:a 1 😛 1}[:not :me 1]{:b 2}])
(transform [(sp/subselect ALL map? :position)]
(partial map-indexed (fn [i x] i))
[{:a 1 :b 1}[:not :me 1]{:b 2}])
no problem
I think you can do that last one with this transform-fn: (fn [aseq] (range (count aseq)))
a little cleaner in my opinion
@conaw: or even better:
(transform [(subselect ALL map? :position) (view count)]
range
[{:a 1 :b 1} [:not :me 1] {:b 2}])
that would be awesome
yea subselect is pretty magical
contributed by @aengelberg
its end result almost outweighs the mutable hackiness I used to achieve it 🙂
lol, I was trying to figure out how I would even achieve this before @nathanmarz mentioned subselect, only thing I could think of was to create an atom
I like this quote from http://clojure.org/transients:
If a tree falls in the woods, does it make a sound?
If a pure function mutates some local data in order to produce an immutable return value, is that ok?
that's a good one
been digging into clojure's transducers and they use a lot of mutability
Subselect gets awkward when working with sets:
(subselect [ALL ALL] reverse [#{1 2 3} [4 5 6]])
=>
[#{6 5 4} [???]]
looks reasonable to me
often I get overly paranoid about confusing beginners
I know what you mean
but I like the clojure philosophy of keep it simple and well defined
even if it requires a learning curve
@aengelberg: curious to hear your thoughts on https://github.com/nathanmarz/specter/issues/121
a lot of overlap with transducers
yeah, just saw that. Seems like it could be even more useful if takenav
could reset at a later level, e.g. (select [ALL ALL (takenav 3)] [[1 2 3 4 5] [6 7 8 9 10]]) => [[1 2 3] [6 7 8]]
essentially the volatile would need to get reset in between the two ALL
s
i think the result you would expect there is [1 2 3 6 7 8]
you might want both behaviors
correct, sorry
thus proving that it's unreasonable to expect that behavior arbitrarily 🙂
so resetting would be an explicit choice
have you considered simply introducing (ALL-transduce (take 3))
that would be one way to do it
then takenav would be a completely different implementation to that
seems like they should unify more cleanly
the degree of overlap is very suspicious
or maybe a "take view"
could be something like (select [ALL ALL (traversed (takenav 3)] ... )
(transform [ALL (subselect (taken 3))] [[1 2 3 4 5] [6 7 8 9 10]]) => [[1 2 3] [6 7 8]]
uhhhh ignore that
(transform [ALL (subselect (taken 3))] inc [[1 2 3 4 5] [6 7 8 9 10]]) => [[2 3 4 4 5] [7 8 9 9 10]]
with the idea there that subselect re-parameterizes its path on every invocation?
that's what I was thinking with traversed
either way the semantics are pretty subtle
maybe too subtle
hey @nathanmarz @aengelberg total aside, but don’t suppose either of you guys know of any great lecturers or youtube channels/videos relating to graph theory.
looks like tim roughgarden has a bunch of videos on graph algorithms on youtube
he's the best teacher I ever had
I was suggesting taken
would be just a regular (not stateful) navigator that only selects or transforms the first N elements
less performant though to do a subselect
@aengelberg: ah, yea I'm thinking more cases like [ALL ALL ALL (takenav 3)]
too many ALL
s 🙂
(select [ALL (freshpath ALL (take-nav 2)) (take-nav 4)]
[[1] [2 3 4] [5 6 7]])
;; => [1 2 3 5]
"freshpath" would mean to treat that path from scratch
the only impact that would have would be to initialize the states and collected vals every time it enters that part of the path