This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2019-12-13
Channels
- # adventofcode (51)
- # announcements (1)
- # babashka (7)
- # beginners (45)
- # berlin (2)
- # bristol-clojurians (1)
- # calva (38)
- # cider (2)
- # clara (25)
- # clj-kondo (2)
- # cljs-dev (25)
- # cljsrn (3)
- # clojure (112)
- # clojure-dev (6)
- # clojure-europe (5)
- # clojure-nl (1)
- # clojure-spec (15)
- # clojure-uk (93)
- # clojurescript (29)
- # clojutre (2)
- # core-async (78)
- # cursive (24)
- # datomic (29)
- # figwheel-main (1)
- # fulcro (50)
- # hugsql (1)
- # hyperfiddle (1)
- # luminus (1)
- # malli (26)
- # off-topic (40)
- # portkey (12)
- # reagent (22)
- # ring-swagger (1)
- # shadow-cljs (56)
- # spacemacs (24)
- # tools-deps (68)
In Clojure, I can use (apply max-key :foo coll)
which will return the entry in the collection with the greatest value of :foo
. If there are multiple entries in the collection (i.e. a vector) and some of them have the same value for the key, then the last element will be returned. Is there a way to get the first element instead of the last?
just watch your perf if coll can be large :)
Just to note too, that rseq works on vectors and sorted maps only, so incase the collection varies in type, i.e can be a list etc, use reverse instead
rseq is potentially faster (in constant time) than reverse.
On the performance front, if not all maps in the sequence will have :foo
or there is some cut off value (like 0
) that you don't care about, you can potentially filter the sequence prior to finding max-key
. This may help manage the size of the list, depending on the density of :foo
.
Another option is to copy the source of max-key, rename it, and tweak its implementation a bit to return what you want.
I think I would prefer the rseq
implementation as then there remains only one version of max-key
. Seems like it would yield less surprise over time. But that's just like my opinion, man. 😉
anyone know how to escape a for loop before completion?
I don't know of one. The result is lazy, so if the code 'consuming' the result stops pulling new elements from it, it will not evaluate the whole result.
So effectively you can 'escape' by appropriate code outside of the for
, but not from within.
alternately, use a reduce and return reduced
value. or use a loop/recur, don't recur.
I guess you could use a :while or :when guard in the for
Hmmm, I've used :when
, which lets you skip generating elements in the returned sequence, element by element, so not really a loop 'escape' if you care about avoiding the linear time of scanning through the rest of the elements. Never used :while
nor seen it in the wild yet.
@U064X3EF3 How can I change the value of a conditional like continue-loop?
from within the loop?
(let [continue_loop? true]
(for [z [1 2 3]
:while continue_loop?]
...))
you can't
you need some stateful device
well I'm running these loops in multiple threads using a taskpool
so I'm a bit nervous to use an atom here
thoughts?
why should you be nervous?
I mean, I would just not use for
when you want to explicitly control a loop, it's best to use loop
but atoms are thread-safe, and you're using them in a per-thread context so they're totally safe (actually, more safe than they need to be for this)
ah good to know. @UQDNANLF2 ^^^
since it's single threaded statefulness, you don't need any synchronization at all, even a 1-slot array would be "safe" (assuming each loop is isolated to a single thread and independent). If you're looking for external control, then different answer (but atoms would be a good option)
I have an atom external to the threads tracking usernames being used within the threads
now I'll have atoms within the threads tracking if loops should continue or not based on success already occuring
I've used atoms within threads on several occasions and haven't encountered any errors
atoms are threadsafe. If you did encounter errors, then something would be gravely wrong.
> atoms within the threads tracking if loops should continue or not based on success already occuring
what I find useful here is using (delay :done)
or (promise)
and then forcing or delivering from the thread that determines the computation is no longer needed
you can use realized?
to check if a delay / promise is still pending
what I like about promises and delays is that they are one way switches, which reduces complexity
Interesting... I've never seen promises in Clojure
a clojure promise isn't like a js one - it's just a location that gets a value assigned exactly once (and you can test whether it's been assigned, and get its value if it has been assigned)