Fork me on GitHub
#clojure
<
2022-11-09
>
ep09:11:38

Hello, is there a reason why a developer would not specify the clojure version in a library’s deps.edn? I assume its own tests then rely on whatever clojure version is specified by the project’s dependencies, using.. the first one in the list? Is the idea to not force the dependency on packages using it?

delaguardo11:11:48

usually library author should specify minimum versions of dependencies. In case the library is generic enough and can work with any version of clojure then enforcing some minimum clojure is not needed.

mx200013:11:38

I released my small 2d game engine based on libgdx: https://github.com/damn/engine

🙌 3
M J13:11:46

(defn products-list-view [data-combined]
  (let assets-selected (r/atom '())]
    (fn [data-combined] @assets-selected
      (let [data (r/atom (map  #(-> %
                                    (assoc :created_at_before (time-ago (% :created_at)))) @data-combined))
            array-of-ticked (r/atom (mapv (fn [e] {:id (:id e) :ticked  false}) @data-combined))]
        [v-box
         :children [[basic-table-with-checkbox {:data data
                                               
                                                :columns {:names ["Name" "Created at" "Last Updates"] :values [:name :created_at_before :updated_at_before] :values-sort [:name :created_at :updated_at]}
                                                :assets-selected assets-selected
                                                :selected-all-ticked? selected-all-ticked?
                                                :selected? selected?
                                                :array-of-ticked array-of-ticked}]]]))))
Lets say I have this component that sends "assets-selected" and "array-of-ticked" When I reset them in the following component, the table, the data rerenders. So on the onChange of checkbox-component, data is changed without me changing it. Any Ideas?
(defn basic-table-with-checkbox [{:keys [data columns assets-selected selected-all-ticked? selected? array-of-ticked]}]
  (fn [{:keys [data columns assets-selected selected-all-ticked? selected? array-of-ticked]}]

    [:<>
     [paper
      [table-container
       [table 
        [table-body
         (map-indexed (fn [index value] 
                        [table-row 
                         (for [columns-name (:values columns)]
                           [table-cell
                            [h-box
                             :children [(if (= :name columns-name)
                                          [checkbox/checkbox-component {:attr {:on-click #(.stopPropagation %)}
                                                                        :onChange #(do
                                                                                     (reset! array-of-ticked (update @array-of-ticked index (fn [e]
                                                                                                                                              (assoc e :ticked %))))
                                                                                     (when-not % (reset! selected-all-ticked? false))
                                                                                     (reset! selected? true)
                                                                                     (if %
                                                                                       (reset! assets-selected (conj @assets-selected {:type (:type value) :id (:id value)}))
                                                                                       (reset! assets-selected (remove #{{:type (:type value) :id (:id value)}} @assets-selected))))}] ())
                                        [:span (columns-name value)]]]])]) @data)]]]]]))

dpsutton14:11:25

no one will ever respond to a wall of text this large. You really need to make your questions far more concise. Dig down to what your actual question is. If you remove all the cruft there's a good chance you can answer it yourself, or someone can quickly answer it for you. But this code requires two screen scrolls on my laptop and there's no way i'll dig through it to figure out what is probably a very straightforward question at the base of it

M J14:11:06

(defn products-list-view [data-combined]
  (let assets-selected (r/atom '())]
    (fn [data-combined] @assets-selected
      (let [data (r/atom (map  #(-> %
                                    (assoc :created_at_before (time-ago (% :created_at)))) @data-combined))
            array-of-ticked (r/atom (mapv (fn [e] {:id (:id e) :ticked  false}) @data-combined))]
        [v-box
         :children [[basic-table-with-checkbox {:data data
                                               
                                                :columns {:names ["Name" "Created at" "Last Updates"] :values [:name :created_at_before :updated_at_before] :values-sort [:name :created_at :updated_at]}
                                                :assets-selected assets-selected
                                                :selected-all-ticked? selected-all-ticked?
                                                :selected? selected?
                                                :array-of-ticked array-of-ticked}]]]))))
Lets say I have this component that sends "assets-selected" and "array-of-ticked" When I reset them in the following component, the table, the data rerenders. So on the onChange of checkbox-component, data is changed without me changing it. Any Ideas?
(defn basic-table-with-checkbox [{:keys [data columns assets-selected selected-all-ticked? selected? array-of-ticked]}]
  (fn [{:keys [data columns assets-selected selected-all-ticked? selected? array-of-ticked]}]

    [:<>
     [paper
      [table-container
       [table 
        [table-body
         (map-indexed (fn [index value] 
                        [table-row 
                         (for [columns-name (:values columns)]
                           [table-cell
                            [h-box
                             :children [(if (= :name columns-name)
                                          [checkbox/checkbox-component {:attr {:on-click #(.stopPropagation %)}
                                                                        :onChange #(do
                                                                                     (reset! array-of-ticked (update @array-of-ticked index (fn [e]
                                                                                                                                              (assoc e :ticked %))))
                                                                                     (when-not % (reset! selected-all-ticked? false))
                                                                                     (reset! selected? true)
                                                                                     (if %
                                                                                       (reset! assets-selected (conj @assets-selected {:type (:type value) :id (:id value)}))
                                                                                       (reset! assets-selected (remove #{{:type (:type value) :id (:id value)}} @assets-selected))))}] ())
                                        [:span (columns-name value)]]]])]) @data)]]]]]))
My qestion is, the ":data data" I am sending, rerenders to previous original value of the r/atom after I change it, and it reverts back to what I originally send on the onchange of chekbox-component When I reset the "Array-of-ticked" and the "Assets-selected". If I removeboth reset!s, it works as it should

p-himik14:11:07

You should move the question to #C0620C0C8

M J14:11:28

Ok I will thanks

Bart Kleijngeld14:11:56

I'm looking for a library that helps me transform nested data structures (trees). I get the impression Metosin recommends Malli their over spec-tools, is that right? Just making sure I'm picking a nice tool for the job. There's also Plumatic Schema, which seems to be an excellent choice as well. Any experiences, recommendations? Perhaps even other tools I might have missed. Thanks!

jake14:11:04

Worth taking a look at clojure.walk not sure what you’re trying to do or if this is appropriate, but certainly could be. https://github.com/clojure/clojure/blob/master/src/clj/clojure/walk.clj

🙌 1
R.A. Porter14:11:18

Depending on the type/complexity of transforms, you might also want to look at Specter - https://github.com/redplanetlabs/specter

🙌 1
Joshua Suskalo14:11:54

also clojure.zip is another one to look at

🙌 1
Bart Kleijngeld14:11:02

To provide a little bit more context: I will be querying a graph database to obtain a model of sorts, which I want to transform to various sorts of target schemas such as OpenAPI, Avro, and possibly SQL DDL code. So I'm looking for something that give me a nice framework for structure declaration and transformation. I've learned about clojure.walk. It's mighty powerful indeed! But I think I'm looking for something broader with more batteries included

👍 1
Joshua Suskalo14:11:54

malli's definitely that

respatialized14:11:59

I think malli probably fits the right bill of combining documentation of the various tree nodes with highly performant parsing and transformation, based on your description, yeah.

Bart Kleijngeld14:11:10

Alright. Thanks for all the suggestions and affirmation

respatialized15:11:11

FYI there's also the #CQT1NFF4L channel for these types of questions should you have more in the future

Bart Kleijngeld15:11:20

I'll subscribe to that one. Thanks

ikitommi15:11:47

Hi. Malli lead here. Just started writing Transforming data with Malli and Meander post. Malli is great for formal validation, data model transformation and simple value transformations. Meander is great for transforming shapes. Malli + Meander = 💕

🙌 1
1
Bart Kleijngeld15:11:09

Thanks. Will the post appear on the Metosin blog? And be announced here in the deref? Would love to read it. In what sense do you mean "shapes"? I can think of a data model as a shape, but you seem to be contrasting them

ikitommi15:11:16

Metosin blog + I’ll link it to #C8NUSGWG6 at least when done. By “shapes” I mean different shapes, collecting data from multiple places into one list, scanning multiple things etc.

gratitude 1
M J14:11:16

I have this: [{:id 2014, :ticked false} {:id 1479, :ticked false} {:id 1490, :ticked false} {:id 0b4d9caf-4c0b-41b6-8fca-46e63915c427, :ticked false} {:id 1993, :ticked false}] How do I update the :ticked to true, for example where id is 1993

tomd15:11:36

This looks like a wrong-data-structure-problem. If this were a map keyed by id rather than a vector of maps, you'd be able to do (update m :ticked not) but as it's a vector, you'd need to do something like this:

(when-let [idx (first (keep-indexed (fn [i m] (when (= 1993 (:id m)) i)) data))]
  (update-in data [idx :ticked] not))

M J15:11:57

This is the data I am trying to change:

array-of-ticked (r/atom (mapv (fn [e] {:id (:id e) :ticked  false}) @data-combined))
its a r/atom that has ids and ticked

tomd15:11:08

ah yes, so you could do (into {} (map (fn [e] [(:id e) false])) @data-combined) instead (if ticked would be the only key)

tomd15:11:15

then you'd have a map rather than a vector of maps

tomd15:11:20

if you have more keys than ticked, you'd want a map of ids to maps, containing :ticked among other things

walterl15:11:31

(almost) what @UE1N3HAJH said initially: (mapv (fn [m] (if (= 1993 (:id m)) (update m :ticked not) m)) data) Agree that it's probably a sign that you want a map with id keys

1
M J15:11:29

Ok so after I changed it, ts like this: {2014 nil, 1479 nil, 1490 nil, 0b4d9caf-4c0b-41b6-8fca-46e63915c427 nil, 1993 nil} How do i change (where :id = 1993)?

tomd15:11:55

just (update m 1993 not) or (assoc m 1993 true) if you want to unconditionally make it true

M J15:11:02

I want to reset ":ticked" just on the mapv of how it was, so I had i tlike this:

(reset! array-of-ticked (update @array-of-ticked index (fn [e]                                                                                                                             (assoc e :ticked %))))
How do I update based on where (= (:id value) (:id %)), and not index

M J15:11:44

I create the r/atom in a page, and update is in another component btw

reefersleep15:11:36

Looks like what you’re trying to express is this:

(swap! array-of-ticked (fn [items]
                         (->> items
                              (mapv (fn [{:keys [id] :as item}]
                                      (cond-> item
                                              (= id (:id %)) (assoc :ticked true)))))))
or something to that effect.

reefersleep15:11:28

Try to break the problem into smaller problems.

M J15:11:18

This is how I create t: array-of-ticked (reagent/atom (mapv (fn [e] {:id (:id e) :ticked false}) @data))

reefersleep16:11:58

Try doing what you want without atoms, using literal example data.

M J16:11:36

Okay, I want to "get index of" a value in an array

reefersleep16:11:41

In a vector, you mean?

M J16:11:16

Yes, the first example I sent

reefersleep16:11:24

I'll have to reply with something other than a phone, later

M J16:11:44

(.indexOf @array-of-ticked "condition that gets by id")

M J16:11:00

so i dont know how to get based on :id

M J16:11:06

Okay I appreicat eit

M J08:11:00

Sorry I should've asked on #C053AK3F9, but since we're here. What condition can I use to target it? I know I think using some will work

reefersleep08:11:01

I must admit that I googled a bit to find the most succinct solution. I rarely operate with indices in vectors, so I had some other solution in mind, but thought it too verbose. As others have suggested, perhaps you could fix your problem by modelling the data differently. I recently refactored in the same manner that they have mentioned, from vector to map, in order to more easily retrieve items from the identifying key. But, in any case:

(let [v [{:id 2014, :ticked false}
         {:id 1479, :ticked false}
         {:id 1490, :ticked false}
         {:id 5, :ticked false}
         {:id 1993, :ticked false}]]
  (->> v
       (keep-indexed (fn [index item]
                       (when (= (:id item) 5)
                         index)))
       first))
;;=> 3

reefersleep09:11:35

The silly solution that initially came to my mind was this. It works, but it’s not nice.

(let [v [{:id 2014, :ticked false}
         {:id 1479, :ticked false}
         {:id 1490, :ticked false}
         {:id 5, :ticked false}
         {:id 1993, :ticked false}]
      result (atom nil)]
  (->> v
       (map-indexed (fn [index item]
                       (when (= (:id item) 5)
                         (reset! result index))))
       doall)
  @result)
Note that the doall is mandatory, or the map-indexed won’t be executed. Which is part of the sillyness 🙂

Noah Bogart15:11:03

hey @seancorfield, i watched https://www.youtube.com/watch?v=75U3W8Y2zzw you gave about using clojure (1.3!), and it's fun to see how your general approach and advice has basically stayed the same over the years. You share code stats at roughly 20 minutes: 35 clj files, 3435 lines. 19 test files, 746 lines, and you mention that you're about to move to expectations.

seancorfield17:11:55

Ah, that's some "ancient" history... here's the stats from our codebase now:

Clojure build/config 22 files 403 total loc,
    163 deps.edn files, 3019 loc.
Clojure source 523 files 106533 total loc,
    4617 fns, 1103 of which are private,
    632 vars, 41 macros, 103 atoms,
    86 agents, 22 protocols, 65 records,
    820 specs, 25 function specs.
Clojure tests 541 files 26582 total loc,
    5 specs, 1 function specs.

Clojure total 1064 files 133115 total loc

Polylith:
   17 bases 382 files 61522 total loc,
   117 components 579 files 48363 total loc,
   19 projects 0 files 0 loc,
  total 961 files 109885 total loc.
Migration 90.31% files 82.54% loc

🎉 1
seancorfield17:11:57

The biggest shift for me has probably been to relying on the REPL more for interactive development. It took me several iterations of editor/plugin to really get where I wanted to be (Atom/Chlorine was the first setup where I was really happy with that -- I started using Atom in 2016 with ProtoREPL and switched to Chlorine in 2018 -- then VS Code/Clover and now VS Code/Calva -- along with REBL, then Reveal, and now Portal).

Noah Bogart18:11:27

I came across this when looking up your "https://www.youtube.com/watch?v=gIoadGfm5T8" talk from a couple years ago. i really gotta try out the Reveal/Portal thing, it seems like a game-changer cuz I currently rely heavily on println-debugging lol

seancorfield18:11:12

I don't even have the (text) REPL window open these days.

seancorfield18:11:25

I use Portal as an extension in VS Code, so I have that as my "REPL" in the editor. And I have it configured so I can run arbitrary Clojure code against the most recent (or a specific selected) value if I need to.

👍 1
cjsauer19:11:54

Is the extension in VS Code what caused you to switch from Reveal to Portal, or were there other reasons?

jpmonettas19:11:40

@UEENNMX0T there is also https://github.com/jpmonettas/flow-storm-debugger if you are tired of println debugging, I created it and use it for that exact reason

👀 1
cjsauer19:11:16

@U0739PUFQ watched your talk and starred! Wow I could’ve really used flow storm just yesterday while debugging an infinite loop in a recursive function I was writing! Can’t wait to try this out.

jpmonettas19:11:12

@U6GFE9HS7 great, show up in #flow-storm if you have any questions

👍 1
seancorfield19:11:23

@U6GFE9HS7 I was switching from Reveal to Portal but it happened to coincide with the VS Code extension being available for testing which was serendipitous. I didn't like the changes Vlad was making to Reveal (the split of a free version and a paid version, and my feeling that he would focus on the paid version features). I'd switched from REBL to Reveal originally because REBL was closed-source and I wanted to be able to modify/contribute to it. It just felt like the same thing was happening with Reveal. And I liked more of what Chris was doing with Portal (and the ease of extensibility since it can be driven by JS/TS/cljs).

seancorfield19:11:31

It's probably worth mentioning that I started using tap> and datafy/`nav` pretty much as soon as they were announced and have come to rely on them very heavily for dev/debug work.

cjsauer20:11:14

All makes good sense. I feel a bit behind the times on these highly visual exploratory tools, trying to catch up a bit. I’m embarrassed by how often I still just sprinkle prn expressions all over and bang rocks together 😅

cjsauer20:11:59

Portal and flow storm both seem like huge productivity boosters

seancorfield20:11:41

For some reason, I've never been a fan of "debuggers"... I think I'm still traumatized by the primitive step debuggers being virtually the only way to make sense of problems back in the C/C++ world (and maybe early in my Java world). I haven't used a "debugger" for over 25 years at this point 😐

cjsauer20:11:25

The only Clojure one I've tried is Intellij/Cursive's built-in one, and it's...not great. It is very clearly not designed for expression-based languages, and ends up just confusing the problem rather than helping. Trace debuggers like flow, with time travel, seem especially effective in a lang like Clojure though, where we have unique benefits that hopefully make it less traumatizing haha

jpmonettas23:11:19

@seancorfield FlowStorm is not a debugger in the C++ sense (stop the world to look at memory, etc) is more inline to what we do with the Clojure repl and portal, where we want to "see the data". The nice thing IMHO is that instead of guessing where to put taps and printlns when you want to understand something, it will instrument the code so when it executes it will just retain the pointers to all intermediate values (we can do this only because of Clojure immutability), so we can then explore execution with a bunch of GUI tools and the repl. It also allows you to instrument anything (your code or a library) without having to write and then remember to remove taps and prints.

jpmonettas23:11:33

so I see it like something to enhance the repl workflow

seancorfield23:11:50

Thanks @U0739PUFQ -- I'll have to carve out some time to take a look at it then.

dev-hartmann15:11:07

hey folks, I have an issue with reading a java.io.File that is a .png Image

dev-hartmann15:11:42

I’m trying to read this with ImageIO/read to check if it’s actually an image

dev-hartmann15:11:49

but it always returns nil

Alex Miller (Clojure team)15:11:30

probably no one can help unless you share some code

Alex Miller (Clojure team)15:11:52

if you do, use the triple-backtick or put it in a snippet, threads preferred to keep topics separate

dev-hartmann15:11:14

sure, that’s the code

dev-hartmann15:11:18

(defn valid-image?
  [image]
  (let [allowed-extensions #{"jpeg" "jpg" "png" "svg"}
        max-size (parse-file-size-units "2 M")
        size (.length image)
        extension (file-extension image)
        parsed-img (ImageIO/read image)]
    (and (contains? allowed-extensions extension)
         (< size max-size)
         (not (nil? parsed-img)))))

dev-hartmann15:11:56

everything works fine, except for the call to (ImageIO/read image)

ghadi15:11:43

break up your predicates, test them in isolation

dev-hartmann15:11:29

I did, parsed-img is nil

ghadi15:11:11

it's unclear what's being passed in

dev-hartmann15:11:25

for parsed img?

dev-hartmann15:11:44

I did a (println (type image))

dev-hartmann15:11:04

it’s a java.io.File that refers to the the correct .png

Alex Miller (Clojure team)15:11:11

does (.exists image) return true?

Alex Miller (Clojure team)15:11:12

also, not sure if you need to call (ImageIO/scanForPlugins) - seems like this uses a plugin architecture that requires adding plugins to the registry

ghadi15:11:57

Clojure 1.12.0-alpha1
user=> (require '[ :refer [file]])
nil
user=> (import 'javax.imageio.ImageIO)
javax.imageio.ImageIO

user=> (ImageIO/read (file "/Users/ghadi/Desktop/image.png"))
#object[java.awt.image.BufferedImage 0x1ddd3478 "BufferedImage@1ddd3478: type = 6 ColorModel: #pixelBits = 32 numComponents = 4 color space = java.awt.color.ICC_ColorSpace@10ec523c transparency = 3 has alpha = true isAlphaPre = false ByteInterleavedRaster: width = 2364 height = 5916 #numDataElements 4 dataOff[0] = 3"]
fwiw I didn't have to scan for plugins.

Alex Miller (Clojure team)15:11:53

I tried it as well, and that worked for me too

dev-hartmann15:11:17

ok, I must be doing something wrong then

Alex Miller (Clojure team)15:11:53

wondering if you are trying to get at a resource on the classpath instead of a file maybe?

dev-hartmann15:11:42

that’s exactly the issue I guess

dev-hartmann15:11:00

i have it in dev-resources

dev-hartmann15:11:06

I’m checking the fn in a deftest and and do have a helper function to give me a java.io.File for the png

Alex Miller (Clojure team)15:11:25

resources are not files (I mean, they are files, but they are independent from the filesystem)

dev-hartmann15:11:35

ah, I just found out, that I slurp the original png, and create a file via http://java.io.file/createTempFile

dev-hartmann15:11:39

and spit the content

Alex Miller (Clojure team)15:11:53

slurp/spit are for character data

dev-hartmann15:11:06

ah, that must be the issue then

Alex Miller (Clojure team)15:11:04

it is still possible to do this though

dev-hartmann15:11:19

I’ll try to create a copy from the png in the resource as a tempFile for my test then

Alex Miller (Clojure team)15:11:33

you don't need to copy it, you just need to read the stream

dev-hartmann15:11:00

ok , will try that, thx!

Alex Miller (Clojure team)16:11:22

(require '[ :as jio])
(ImageIO/read (jio/input-stream (jio/resource "yes.png")))

Alex Miller (Clojure team)16:11:23

that will read the png as a stream of bytes from the resource on the classpath

dev-hartmann16:11:12

ah, now it works! my way spitting in the temp file was the issue, when taking the input stream it works fine! thanks @U064X3EF3 @U050ECB92

seancorfield17:11:55

Ah, that's some "ancient" history... here's the stats from our codebase now:

Clojure build/config 22 files 403 total loc,
    163 deps.edn files, 3019 loc.
Clojure source 523 files 106533 total loc,
    4617 fns, 1103 of which are private,
    632 vars, 41 macros, 103 atoms,
    86 agents, 22 protocols, 65 records,
    820 specs, 25 function specs.
Clojure tests 541 files 26582 total loc,
    5 specs, 1 function specs.

Clojure total 1064 files 133115 total loc

Polylith:
   17 bases 382 files 61522 total loc,
   117 components 579 files 48363 total loc,
   19 projects 0 files 0 loc,
  total 961 files 109885 total loc.
Migration 90.31% files 82.54% loc

🎉 1
Annie Carlson20:11:25

Does anyone know of a tool that finds unmaintained dependencies? I'm hoping to set up an alert on some repos, perhaps in the CI integration or just in a script, that lets me know when dependencies I'm using haven't been updated in a determined amount of time.

p-himik20:11:31

But why? I use a lot of dependencies that haven't been updated in years. It might easily go to 30-50% of all dependencies in particular projects. It doesn't mean those dependencies are bad - it's just that they fill the niche they wanted to fill.

lread20:11:25

If you are looking for deps that have new versions available, https://github.com/liquidz/antq is a very nice tool.

gratitude-thank-you 1
Annie Carlson20:11:10

Thanks! p-himik, I want to know if a dependency I am using is out of date so that I can make an informed decision about continuing to use it.

seancorfield21:11:34

Clojure is unusual in that a lot of libraries are "done" because they are small and focused so you get lot of very widely used libraries that haven't had substantive changes for years. Look at many of the Contrib libraries for example. In other language ecosystems, a library that hasn't been updated for a while is usually considered "abandoned" and folks start to look for alternatives.

❤️ 1
seancorfield21:11:02

One of the libraries we rely on at work hasn't had a commit in nearly seven years. Still works perfectly on the very latest release of Clojure.

seancorfield21:11:45

OTOH, we run antq on at work several times a week and always look at any updates (and usually apply the Clojure ones -- typically safe, whereas the Java ones always need more investigation: Clojure devs are much, much better about backward compatibility than in most languages!).

Joshua Suskalo21:11:30

I want to add another affirmation of this: old dependencies are probably fine, dependencies which have published updates are worth investigating.

p-himik21:11:38

> so that I can make an informed decision about continuing to use it. What would inform such a decision?

borkdude21:11:17

Perhaps unreplied issues / PRs is a better sign of unmaintained than last commit date

👍 2
Annie Carlson21:11:03

>> so that I can make an informed decision about continuing to use it. > What would inform such a decision? Sometimes I have found that a library is absorbed into another actively maintained library. This change can be easily overlooked by a dependency checker. There may be other cases as well, such as the readme loudly declaring its deprecated.

👍 1
p-himik21:11:29

Right, but neither of those are directly indicated by a library not having an update in a long time. And even if it is an indication, you would have to wait that aforementioned long time before you actually obtain that information. I find a careful per-project vetting of your dependencies to be a much better approach, if a bit tiresome at times. Just a single counter-example to what you describe - I still use com.cemerick/url in one of my projects even though it's been unmaintained for 9 years. Simply because it works for that projects - there's no need for me to invest time and effort to switch to something else.

Annaia Danvers22:11:08

I think it's reasonable to be concerned if a dependency has not been maintained in some time. While I respect and mostly agree with the "if it ain't broke" philosophy in Clojureland ... sometimes something *is broke*, and no one was around to notice or fix it.

💯 2
Annaia Danvers22:11:24

I get itchy especially about security concerns, both directly and through transient dependencies. It has been very eyeopening at times doing Clojure in an environment where we have a vuln scanner on our Maven deps.

seancorfield23:11:29

We run clj-watson regularly at work and the three open CVEs we have reported right now are in Google (Java) libs that are very widely used and have no updates/fixes available 😞

seancorfield23:11:48

I guess the general smallness and simplicity of many Clojure libraries is what protects us from CVEs -- that and the relative small niche that we live in not being the target of many attack attempts?