This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2022-10-24
Channels
- # aws (2)
- # babashka (27)
- # beginners (97)
- # calva (1)
- # cherry (12)
- # cider (6)
- # clara (12)
- # clj-kondo (24)
- # clj-on-windows (4)
- # cljfx (14)
- # clojure (54)
- # clojure-australia (3)
- # clojure-europe (26)
- # clojure-nl (1)
- # clojure-norway (4)
- # clojure-uk (9)
- # clojurescript (65)
- # conjure (5)
- # cursive (7)
- # datomic (18)
- # emacs (6)
- # helix (2)
- # honeysql (1)
- # jobs (1)
- # joyride (15)
- # kaocha (2)
- # lsp (10)
- # malli (5)
- # nbb (12)
- # observability (5)
- # off-topic (5)
- # reitit (2)
- # releases (4)
- # ring (1)
- # sci (17)
- # shadow-cljs (34)
- # testing (29)
- # tools-deps (45)
- # vim (7)
- # xtdb (6)
@borkdude looks like there may be a false positive for unused value when checking mutative transient calls?
src/cognician/base/coll.cljc:151:17: warning: Unused value
src/cognician/base/coll.cljc:162:16: warning: Unused value
(defn distinct-by
"Keeps items which have distinct `(key-fn item)` results. Not lazy"
([key-fn]
(fn [rf]
(let [^clojure.lang.ATransientSet seen (transient #{})]
(fn
([] (rf))
([result] (rf result))
([result input]
(let [key (key-fn input)]
(if (.contains seen key)
result
(do
(conj! seen key) ;; <----- here
(rf result input)))))))))
([key-fn coll]
(let [^clojure.lang.ATransientSet seen (transient #{})]
(persistent!
(reduce
(fn [res item]
(let [key (key-fn item)]
(if (.contains seen key)
res
(do
(conj! seen key) ;; <----- here
(conj! res item)))))
(transient []) coll)))))
That is correctly flagged, it is an example of "bashing in place" which the transient docs say not to do
The transient mutating operations all sometimes return a new object and sometimes mutate the existing object, so you cannot ignore the return value
fascinating, TIL, thank you!
This is the whole reason for volatile!
to exist, in fact
Not really, volatile is just a more performant atom without concurrency safety https://clojure.atlassian.net/browse/CLJ-1512
Maybe I wasn’t clear enough. I don’t mean replacing stateful transients but acting as transducer state management (as demonstrated in your link). Robert’s transducer above is using transients to hold transducer internal state and that is the domain of volatile!.
In a transducer?
The problem seems to be manifesting with transient of map more than anything else though:
user=> (let [t (transient #{})] (doseq [i (range 10000)] (conj! t i)) (count (persistent! t)))
10000
user=> (let [t (transient {})] (doseq [i (range 10000)] (conj! t [i i])) (count (persistent! t)))
8
using transients not according to how all the docs say they can be used is less likely to lead to an observable bug with sets, but is still ignoring the docs
I do agree (and this is the main reason we now have :unused-value
actually), but just to be clear, which docs are you referring to - the docstrings of transient
and conj!
or the Clojure website?
I think the exclamation marks send people in the wrong direction, thinking that it's bashing in place, so the return value doesn't matter that much
or a linter that marks using transients as an error until the user pinky swears that they have read the docs
or just :unused-value, and then they'll ask here and have "the conversation" on transients :)
"the conversation" 😂
Feature request (or "please show me where the existing feature that I can't find is" request): option to check that every file ends in a single newline. WDYT?
@dchelimsky All available linters are here: https://github.com/clj-kondo/clj-kondo/blob/master/doc/linters.md All available configuration options are here: https://github.com/clj-kondo/clj-kondo/blob/master/doc/config.md Your request isn't in there yet, but is very similar to the :line-length linter, implementation-wise https://github.com/clj-kondo/clj-kondo/blob/master/doc/linters.md#line-length Feel free to post an issue and if you want I could guide you how to implement it as well
@borkdude it's been suggested that this should be a cljfmt thing. WDYT?