Itβs almost like a lazy transducer?
Good morning btw!
Morning
Happy Friday!
Morning
@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.
morning
morning. The KLF rules.
despite burning a million quid.
despite because
morning
@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))
@slipset isn't first-invalid
just or
maybe?
You might very well be right.
Damn!
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
Hmm, I have a bug in my implementation π
> (all-invalid (error 1) (or (ok) (error 4)) (all-invalid (error 2) (error 3)))
;; => ("ERROR-1" "ERROR-4" (["ERROR-2" "ERROR-3"]))
I need them to un-nest, and I'm scared of using flatten
I wonder if malli has something like "all errors" and "first error"
I would want this to be ("ERROR-1" "ERROR-4" "ERROR-2" "ERROR-3")
a small sprinkle of seq?
maybe?
(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.
what are people using to read/write bzip2 files?
@otfrom raynes/fs has a compression namespace for this
it uses some apache compression lib under the hood
the lib is now maintained under clj-commons
cool, that has been adopted by clj commons as well
snap
(I still feel sad about raynes)
me too!
nice fact, the fs.clj
namespace can now run from source with babashka
cool
@slipset I like your last comment on that repo
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 should dig out my old example)
I think cgrand/xforms has something
@otfrom https://blog.michielborkent.nl/2018/01/17/transducing-text/
you are my hero today @borkdude π
ah, building on the grammarly work (that was where I started)
@borkdude glad you saved that as the original has disappeared from their blog
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/
I think they changed their links
(cool URLs don't change, didn't anyone tell grammarly that?)
Fixed the link on my blog
π
this is what I did last time: https://clojurians-log.clojureverse.org/clojure-uk/2017-11-30/1512059055.000520
I have a Java class like this: java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask
but how do I type hint this in order to avoid reflection?
ok I think I got it....
type hint the with the whole class path... I tried that... but I got an error else where... type hint that as well. and now it all seems to work.