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
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
Oh, look at that https://stackoverflow.com/a/16240426
nice! all good ideas, thanks
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
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
โข Aleph (wraps Netty): https://github.com/clj-commons/aleph โข rolling-stones (wraps Sat4J): https://github.com/Engelberg/rolling-stones
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
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(alter-var-root #'index-data memoize)
from his amazing https://github.com/halgari/build-your-own-logic-engine/blob/master/src/build_your_own_logic_engine/core.clj#L350
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)))))
Nice!