This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2020-10-09
Channels
- # announcements (1)
- # aws (2)
- # babashka (3)
- # beginners (39)
- # calva (6)
- # chlorine-clover (20)
- # cider (9)
- # clojure (105)
- # clojure-australia (1)
- # clojure-europe (64)
- # clojure-france (2)
- # clojure-gamedev (2)
- # clojure-nl (10)
- # clojure-provo (1)
- # clojure-uk (21)
- # clojuredesign-podcast (1)
- # clojurescript (77)
- # clojurewerkz (2)
- # clojutre (1)
- # community-development (4)
- # conjure (13)
- # data-science (6)
- # datascript (10)
- # datomic (37)
- # fulcro (33)
- # graphql (23)
- # jobs (1)
- # luminus (2)
- # malli (12)
- # meander (2)
- # off-topic (42)
- # pathom (5)
- # re-frame (5)
- # reitit (3)
- # remote-jobs (6)
- # reveal (38)
- # shadow-cljs (2)
- # spacemacs (14)
- # specmonstah (1)
- # sql (8)
- # tools-deps (2)
- # vim (8)
- # xtdb (22)
@dharrigan America: What Time Is Love is still a thing of beauty.
Good morning!
I just saw the discussion about rich comment block. I like them and use them and have colleagues who hate them and remove them left and right. They main argument is that they are often outdated when the codebase changes and should be unit tests actually. This missed the point that they are a vehicle to quickly setup an environment to continue working on the codebase.
@ordnungswidrig rich comment blocks afford exploring a code base in a different way from unit tests
@ordnungswidrig outdated rich comment blocks: this is also why clj-kondo defaults to linting them. I can see immediately if they are outdated in my editor.
@borkdude Great decision
The problem with them being outdated happens if other developers donβt use them and ignore them when changing the code. As so often itβs a matter of communication and sticking with decisions.
Oh, a Clojure win. I've been spending my time in some, let's say, poorly written validation code. When I started digging into this, my Java-reptile brain thought: "oh, cool, maybe I can create a lib out of the validation-running logic and open-source it?" After a while, I ended up slightly modifying a core macro in two different ways, and I had what I wanted:
(defmacro first-invalid
"Returns the result of the first validator which returns non-nil"
[validator & validators]
(let [valid? (gensym)
validations (map (fn [next-validation]
`(if-not (nil? ~valid?) ~valid? ~next-validation))
validators)]
`(let [~valid? ~validator]
~(if (empty? validations)
valid?
(last validations)))))
(defmacro all-invalid
"Returns the result of all the validators which returns non-nil"
[& validators]
(let [validations (vec
(keep (fn [next-validation]
`~next-validation)
validators))]
`(remove nil? ~validations)))
And I'm sure they could be written better, but that's not the point, the points are: 1. I've finally produced some interesting macros 2. This would have been a metric shit ton of code in Java.
@slipset can you give an example of calls to these macros? only the code is a bit unimaginative to look at
(all-invalid (validate-user-name username) (validate-first-name firstname) (validate-last-name)) ;; will run all validators
(first-invalid (not-empty? possible-number) (number? possible-number))
For the second one I would probably write a reduce
, merge
, merge-with
or just []
, no need for a macro if you want to eval all anyway
> (all-invalid (error 1) (or (ok) (error 4)) (all-invalid (error 2) (error 3)))
;; => ("ERROR-1" "ERROR-4" (["ERROR-2" "ERROR-3"]))
(defn collect-errors ([err1 err2] (if (seq? err2 ) (cons err1 err2)) ([err1 err2 & errors] ....)
in malli, the validation errors is a sequence, you can ask just the first. but, populating the sequence is currently eager, for no good reason :thinking_face: validation is optimized to fail-fast on first error.
could be lazy-seq, so the find-first would work as expected. I guess that would be useful in case you have 1000 large items in a sequence to validate and just need to find the first failing reason.
https://github.com/clj-commons/fs/commit/642e0e6fc734b0855a4579d4518073b2192ac0ef
so fs looks good if I want to copy the bzipped file over. I want to read in the lines. I've done that with an eduction before (I think). Are there any good examples of reading in from a file into a transducer that produces records/lines?
I just googled it: https://www.grammarly.com/blog/engineering/building-etl-pipelines-with-clojure-and-transducers/
ah, just the link coming from your blog that 404s https://www.grammarly.com/blog/engineering/building-etl-pipelines-with-clojure/
this is what I did last time: https://clojurians-log.clojureverse.org/clojure-uk/2017-11-30/1512059055.000520