Fork me on GitHub

Hello, I'm having an issue with clj-kondo and honeysql because honeysql helpers are macros and clj-kondo doesn't recognize those macros. I tried configuring clj-kondo as in honeysql's but now, instead of a unknown symbol warning, I'm getting an error because it expects (select :field1 :field2 :field3) to have only 2 arguments.. anyone had issues like this before?


Ask in #clj-kondo but I think there’s a “catch-all” def style linter you can have it lint-as that might help?


I'll put the question there


I want to ship an uberjar foo.jar to my users that will allow them to optionally create a sibling file config.edn if they want to override defaults. what's the right way of locating this config.edn in my code so I can read it?


Depends, using -D to set a jvm property to point to the file and read it is not uncommon

👍 3

Depending on how your uberjar is being used you might stipulate that the config file be on the classpath and use io/resource to load it


(combining classpath specification with uberjars can be a little whacky though)


oh duh, yeah, making it a param is not a bad idea. still curious about whether there's a not-terribly-hacky answer to my original question though


The user.dir system property gives you the current working directory when the jvm is launched, but that may not have anything to do with where your jar file lives


You can do something like look up a resource you know is in your jar, the url you get back will have the path to your jar file in it, so munge that

👍 3

nice! all good ideas, thanks

Janne Sauvala17:05:39

Does anyone know good tutorials, articles or example repos of good ways to wrap Java/JS libs with Clojure(Script)? I’m interested in looking best ways to wrap libs that are mutating their internals and how to handle those smoothly in Clojure


some quick tips on making lib's mutability more safely consumable: - wrap the op under a threadlocal - create an object once per defn invocation and don't let references to it 'escape' to callers


the core idea is that a properly designed OOP lib, though mutable, will have that mutability limited to single objects (vs. global mutability). So it's fairly easy to control a single object


In general though if a lib is a stateful thing and that statefulness can't be "contained" then you will need to use the standard mechanisms for controlling that


e.g. the system pattern


obvious sort of example would be a database pool


and maybe that means there isn't going to be much benefit to doing a clojure wrapper beyond syntax convenience

Janne Sauvala20:05:28

Thanks for the examples and tips. Like Ethan said, I think in my case that I have been thinking most of the benefit is coming from the nicer syntax when using with Clojure. It started to be quite tedious to write interop code all the time so I’m thinking about writing a wrapper to do my bidding


What's the idiomatic way to apply a decorator to a function defined with defn? Replace the defn's with (def decorated (decorator (fn ...)))?


(defn foo [])
(alter-var-root #'foo decorator)
i saw tim baldridge do this with memoize and thought it was interesting


That certainly looks better, thanks! 🙌


Best of all, it doesn't offend Eastwood in the way that my re-def-ing did 😅 🎉


another option:


(defmacro defmemo
  "Define a function with a memoized implementation."
  [& defnargs]
  `(doto (defn ~@defnargs)
     (alter-var-root #(with-meta (memoize %1) (meta %1)))))

Ben Sless06:05:49

I always wandered how that interacts with direct linking and aot compilation. Anything I should be wary of?

🤷 2