This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2018-02-03
Channels
- # beginners (48)
- # boot (26)
- # cider (7)
- # cljsrn (1)
- # clojure (137)
- # clojure-nl (1)
- # clojure-spec (5)
- # clojure-uk (18)
- # clojurescript (26)
- # cursive (8)
- # datascript (4)
- # datomic (4)
- # defnpodcast (11)
- # docker (1)
- # duct (7)
- # figwheel (4)
- # fulcro (7)
- # off-topic (7)
- # re-frame (46)
- # reagent (40)
- # reitit (3)
- # shadow-cljs (4)
reduce
is left to right. is there a generic way to reduce right to left, without a) reversing the collection or b) using the reducers library?
https://stackoverflow.com/questions/16800255/how-do-we-do-both-left-and-right-folds-in-clojure
seems like the answer is, 1) try not to need foldr and 2) use the reducers library
if the input is a vector, rseq
is cheap unlike reverse
it's not cheap to reverse a clojure list?
it's because vectors are optimized for indexing?
no, you have to consume the whole thing - it's O(n)
because vectors are indexed, and have cheap methods for walking in reverse
sorry - that is, reversing list or seq is not cheap, you need to consume the whole thing in order to construct it, a vector is cheap because there's a simple way to consume it end to beginning order, rseq
packages that as a feature
gotcha
i take it it's idiomatic to recursively invoke a function if you are handling multiple arities. can anyone confirm?
e. g.
(defn tax-amount
([amount]
(tax-amount amount 35))
([amount rate]
(Math/round (double (* amount (/ rate 100))))))
yes, that's the correct way to do multiple arities
because even though the stack frames will be left open, it won't be very deep?
right - it's bounded to one - there's a lot of standard clojure idioms that go deeper than that
(every use of a var by name does a var lookup implicitly, for example)
assoc-in
is defined recursively
user=> (source assoc-in)
(defn assoc-in
"Associates a value in a nested associative structure, where ks is a
sequence of keys and v is the new value and returns a new nested structure.
If any levels do not exist, hash-maps will be created."
{:added "1.0"
:static true}
[m [k & ks] v]
(if ks
(assoc m k (assoc-in (get m k) ks v))
(assoc m k v)))
i thought this was not correct?
it's something that can't be done with recur
unless you create an extra local binding to represent the pending parent data structures as you go
why wouldn't that have been done here, in the clojure source code?
because an extra local to capture the pending data structures increases the complexity of the code quite a bit
(plus the extra step to wrap it all up again)
well bless my nippers
bless them all day long!
if i'd known this was permitted for short collections...
all along!
be wary of get-in
, assoc-in
et. al if you’re trying to write tight loops with high performance, they are fast enough for general use but in those cases they don’t cut it
@U3L6TFEJF what alternative to assoc-in
would you use if you did need the performance?
for me, two options: either https://github.com/nathanmarz/specter, or write a method and unroll it manually
see https://gist.github.com/nathanmarz/b7c612b417647db80b9eaab618ff8d83 for some examples
wow, this is terrific
and gratifying to see confirmation that "querying and transforming nested and recursive data is complex in vanilla clojure"!
good to know
if the recursion depth is known at invoke time and is quite small no reason to avoid recursion
maybe it's that with nested maps, in order to add another innermost map, you have to traverse the entire nested structure. and you'd do that every loop, going one level deeper each time
i think you have to keep track of the sequence of keys you used to get to where you are as well as the in-progress, pending result
compared to cons-ing a list together item by item as you go, for example, where there's no need to understand "where you are" in that list
in an imperative style, you'd have a cursor and mutate as you go and have no need to recreate the map as a whole every time
as opposed to either imperative style in place mutation or real recursion, loop/recur
seems to be uniquely difficult
and maybe you can't always express these other algs into loop/recur
i guess i saw that earlier today with the lack of foldr