This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
- # announcements (1)
- # aws-lambda (3)
- # babashka (6)
- # beginners (91)
- # bristol-clojurians (5)
- # calva (25)
- # chlorine-clover (8)
- # cider (6)
- # clj-kondo (13)
- # cljdoc (10)
- # cljsrn (1)
- # clojure (80)
- # clojure-berlin (6)
- # clojure-europe (29)
- # clojure-nl (4)
- # clojure-spec (18)
- # clojure-uk (51)
- # clojurescript (41)
- # conjure (55)
- # cursive (3)
- # datomic (58)
- # emacs (9)
- # events (1)
- # figwheel-main (2)
- # fulcro (29)
- # graphql (12)
- # helix (4)
- # jobs (4)
- # klipse (8)
- # london-clojurians (1)
- # malli (5)
- # off-topic (13)
- # portal (9)
- # re-frame (30)
- # shadow-cljs (44)
- # spacemacs (7)
- # specter (3)
- # sql (11)
- # tools-deps (71)
- # windows (1)
- # xtdb (10)
Is it normal to define multimethods like this
(defmulti my-fn #(mapv type %)) to achieve a sort-of function overloading in Clojure?
what's a good way to count the number of times a given predicate function returns true when mapped over a sequence? E.g.,
(count-matches odd? [1 2 1 3 -4 -5]) should return 4. Perhaps
(count (filter ???)) but there's really need to create a new sequence.
transducers should not create intermediate sequences
(count (sequence (comp (map odd?) (filter identity)) [1 2 1 3 -4 -5]))
@U010VP3UY9X are you worried about the GC from doing?
That seems like an unnecessary concern.
(count (filter odd? [1 2 1 3 -4 -5]))
In this case, I only want to know whether count is > 1. I guess I could write my own with reduce/reduced
(not (empty? (rest (filter odd? ...)))) BTW odd? is just an example, in my case the predicate is more costly.
nah, that's just my convention; it's actually
(->> (filter ..) (drop 1) seq some?) or perhaps
(->> (filter ..) (drop 1) empty?)
My original point still stands - don't be so worried about the performance of lazy-seqs; unless you can measure actual slow performance. In this case, you do probably just want
(second (filter pred some-coll)) ;]
what about just
(rest (filter pred some-coll)) but as I understand an empty collection is not false. That's why I said
(not (empty? (rest (filter red some-cool))))
There is also
not-empty if you are so inclined; or
next that will return
nil only if the rest is an empty list.
> There can be no `nil`, because it would have been filtered out
ah right -- I didn't think of
(pred nil) => something-truthy
seq that can quickly tell you if the count is greater than 0
(nil? (next (filter pred some-coll)))
(< (bounded-count 2 (filter pred some-coll)) 2)
> There can be no `nil`, because it would have been filtered out
I don't understand this claim. Of course I can have a predicate which returns
true when its argument is
nil among others
I think (seq x) is the better way to do (not (empty? x)) https://clojuredocs.org/clojure.core/empty_q
Yes I've had this discussion several times before. For me
seq does not express the intent of
(not (empty? ...)) and in my opinion the compiler should compile them to the exact same instructions, but it fails to (or refuses to) do so.
If programmers should always use
(sec ...) in place of
(not (empty? ...)), then the compiler should do that for me.
Following on from a discussion in #clojure-uk, I'm trying to wrap my head around the information presented here
Since Var roots are global for the entire application, once the body of the future gets around to deref-ing the var (after the 1 sec pause) the root value has already been reset back to 0, causing a race condition.
I just don't understand however, what is meant
the root value has already been reset back to 0, causing a race condition.
What is throwing me is this
the root value has already been reset back - it suggests to me that something behind the scenes is changing the value of the var back to the value of
What if the future executed more quickly, before the
with-redefs completes? That's your race condition.
The with-redefs in this example doesn't seem to be doing anything much, it's wrapping a future.
The same code with different results.
user=> (defn foo  0) #'user/foo user=> (with-redefs [foo (fn  42)] (future (println (foo))) (dorun (range 1))) nil 0 user=> (with-redefs [foo (fn  42)] (future (println (foo))) (dorun (range 1))) 42 nil user=>
with-redefs completes, the value is reset back to what it was before
I must have a faster machine 🙂 I have to bump the range up to nearly 1000 to have differing results
It would make sense to me, if the line was instead of
the root value has already been reset back to 0, causing a race condition. it was
the root value has already been reset back to 42, causing a race condition.
the race is that you have code expecting the value to be 42 and code that will change the value back to 0. the order of those events is not deterministic and therefore you have a race
sometimes the future will execute in totality first, sometimes the resetting back to 0 will happen first, sometimes the future will execute some portion with 42, then some portion with 0. its a race
the root value is
reset back to 0 after
with-redefs completes. It is not
reset back to 42.
with-redefs temporarily sets it to (return, in my case)
42 -- and then resets it back to (return)
Riiigh, so is it a typo then on that line? Should it be
reset back to 42, causing a race condition. not
reset back to 0, causing a race condition.
I assumed, based on the quote, it was doing what I showed. But, yeah, the article should say "reset back to 42".
(I mistakenly assumed the article was correct and you were just confused about why there was a race condition 🙂 )
> What is throwing me is this the root value has already been reset back - it suggests to me that something behind the scenes is changing the value of the var back to the value of 42.
with-redefs is gross (but it is also still very useful if you know you won't have any race conditions)
Now I get it, the with-redefs sets the answer to be 0, but it modifies the root binding, only for the duration of that block. When the block exits, the value is put back to 42, in the meantime, the future inside that block will complete at some point and where you the programmer was thinking that the value of the answer would be
0, it's now
42 because it's been reset back
Well, it may or may not have been reset back. Hence you may get zero or you may get forty-two.
Yes, and I appreciate it - it helped to futher solidify my understanding and help figure out that the article was a little misleading 🙂
Just to prove it can happen with a simple Var, set to
42 initially and
Took me about half a dozen repetitions to see the value flip.
user=> (def answer 42) #'user/answer ... user=> (with-redefs [answer 0] (future (println answer)) (dorun (range 1))) nil 42 user=> (with-redefs [answer 0] (future (println answer)) (dorun (range 1))) 0 nil user=>
Would it be impolite to reach out to Tim to ask him to review the material and look to update the post?
Others may stumble across it (or be linked to it, from a discussion in another channel) and end up being confused too 🙂
Thank you everyone. I've reached out to Tim with the hope he might consider the change to the blog post 🙂
I didn't actually read all that backchat, but if you could summarize what needs to be updated, I can probably do so