This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2022-01-06
Channels
- # adventofcode (10)
- # ai (2)
- # aleph (2)
- # announcements (21)
- # beginners (25)
- # calva (7)
- # cider (19)
- # clj-kondo (28)
- # clj-on-windows (3)
- # cljdoc (6)
- # clojure (80)
- # clojure-dev (15)
- # clojure-europe (29)
- # clojure-italy (3)
- # clojure-nl (37)
- # clojure-uk (4)
- # clojurescript (3)
- # cloverage (1)
- # conjure (6)
- # core-async (2)
- # cursive (17)
- # datalevin (9)
- # datomic (7)
- # deps-new (23)
- # emacs (4)
- # figwheel-main (6)
- # fulcro (6)
- # honeysql (19)
- # improve-getting-started (4)
- # inf-clojure (2)
- # introduce-yourself (5)
- # jobs (1)
- # leiningen (6)
- # lsp (73)
- # malli (1)
- # nrepl (2)
- # off-topic (37)
- # polylith (9)
- # quil (2)
- # reitit (16)
- # releases (2)
- # remote-jobs (6)
- # rewrite-clj (38)
- # shadow-cljs (1)
- # tools-build (1)
Heya folks! I need to monkey patch a function in code I don't control. I understand two methods to do this are to enter the namespace and redef it, or to intern
the var. Is there a stable way to ensure that the intern
/monkey patch is invoked after the lib loads?
For example, when executing tests on some code related to the monkey-patch, I need to ensure that the related monkey patch is applied after loading the dep and before running the test. So I can stick the monkey-patch in the namespace that's being tested, but it seems like there should be a nicer way to declare that "I depend on this monkey patch" so that the loader will handle this for me?
What about this, this didn't work? https://clojuredocs.org/clojure.core/with-redefs
Ah I should clarify that I do have something working (doing in-ns
and deffing it), but I'm looking to improve it 🙂 with-redefs
is an option but I think I'd have to wrap it around my whole app and I'm not sure it solves the testing problem
Then make your own version of that library that exposes what you want...?
Also a possibility 🙂 Would be nice if it was possible to do without though, since it's a 3 line change...
Then you can copy the source code and do your change...
But that's not very upgradeable
Yeah and it's an internal function so I'd rather not copy a bunch of source code to get "deep enough" to where I can patch what I need
I needed something in golang for my master's. And there simply was no other way. I copied the sources and called it a day.
In clojure people may have small functions which would allow to hack and compose everything yourself. But in golang they have large blobs with lots of ifs. And if I understand you have the latter.
Also library authors in clojure sometimes make all internal variables private. Which blocks to do this monkey patching even if you want it.
Anyway. You could use reflection and code generation. But it's too sophisticated. You could look how PowerMock and Mockito work. And try something of that sort (heavy reflection).
Mockito can replace methods on a class. PowerMock can replace methods on a static final class (at least static for sure) and constructors, singletons.
> Also library authors in clojure sometimes make all internal variables private. Which blocks to do this monkey patching even if you want it. You should be able to reference the var directly even if it's private
Anyway, I guess my core issue is not how to do the monkey patching -- I have something that works. More how to ensure the monkey patch is applied consistently
You could run it in your main method. Who knows.
I think separate library is the most consistent and you will know that you do it every time.
Also you could have a build process that checks the library for you
So long as you require the namespace containing the var you want to patch before you patch it you can be sure your patch is applied after the initial load of the namespace. It doesn't guarantee that the library (or another library) doesn't monkey patch it's own var after that, but that would be pretty unusual.
When I monkey patch, this is how I do it:
(defmacro defpatch
"An anaphoric macro for patching existing functions. Original function is bound to the symbol 'this'.Safe to execute multiple times, 'this' will always refer to the original implementation and never the previously patched implementation."
[symbol bindings & body]
`(let [var# (var ~symbol)]
(alter-var-root var#
(letfn [(define# [orig#]
(let [~'this orig#]
(with-meta (fn ~bindings ~@body)
(merge (meta orig#) {::original orig#}))))]
(fn [original#] (define# (or (some-> original# meta ::original) original#)))))
var#))
What's the best way to parse a string into an integer?
You already have set your constraint. You want it to be an integer. So probably it would be java.lang.Integer that you want. There is a function in Java's stdlib for that. But even then. This may have been clojurescript question. And there is no easy way to parse exactly integer without a floating point part.
Integer/parseInt
or Long/parseLong
, although IIRC parse-int
is to be added in the latest and greatest version of Clojure?
@U46C250QM yes, but look at his title: "Author of Data-Oriented programming" This is not the guy who would ask this question to get the answer 😄
of course, but he asked a simple question with a simple answer 🙂 perhaps he intends to ask a different question
I didn't get the joke about the title of my book:hugging_face:
If you have that kind of a book then you can lookup the answer on your own. So probably the question was not what you were asking for.
In my book I deal with "principles" not with low-level implementation details:joy:
The answer @U46C250QM provided is exactly what I was looking for.
I would always prefer clojure.edn/read-string
for any parsing purposes, but I guess it depends on the use case.
Sometimes you want to fail fast and with an exception. But edn reader would also be fine if you'd check that you get a number.
Reading will read the next token from a string, and is inherently a different semantic than parsing.
You mean because
(clojure.edn/read-string "123 4") => 123
?yeah. (clojure.edn/read-string "1 fish 2 fish") ;; => 1
or even "1.234" returning a double when you want to parse a long. parsing has extra expectations - you want to parse the entire input and return a value of the expected type. In Clojure 1.11, we'll have parse-long
, parse-double
, parse-boolean
, and parse-uuid
added
reading is more about tokenization/lexing and reads the next valid token of any type
So for now, the way to go is Long/parseLong
?
Hi I am trying to use clj-async-profiler [https://github.com/clojure-goes-fast/clj-async-profiler] but it fails for me with
JDK9+: you must start the JVM with option -Djdk.attach.allowAttachSelf, otherwise the agent will not be able to dynamically attach to the running process. For Leiningen, add :jvm-opts [“-Djdk.attach.allowAttachSelf”] to project.clj. For Boot, start the process with environment variable BOOT_JVM_OPTIONS=“-Djdk.attach.allowAttachSelf”.`
I’ve added the required option to dev
alias
:dev {:extra-paths [“env/dev/clj”]
:extra-deps {clj-commons/clj-yaml {:mvn/version “0.7.0"}
criterium/criterium {:mvn/version “0.4.6”}
pogonos/pogonos {:mvn/version “0.1.1"}
ubergraph/ubergraph {:mvn/version “0.8.2”}
vlaaad/reveal {:mvn/version “1.3.196"}
com.clojure-goes-fast/clj-async-profiler {:mvn/version “0.5.1”}
binaryage/devtools {:mvn/version “0.9.10"}}
:jvm-opts [“-Djdk.attach.allowAttachSel” “-XX:+UnlockDiagnosticVMOptions” “-XX:+DebugNonSafepoints”]}
and REPL started with command (generated by cider jack-in):
/usr/local/bin/clojure -Sdeps ‘{:deps {nrepl/nrepl {:mvn/version “0.9.0"} cider/cider-nrepl {:mvn/version “0.27.4”}} :aliases {:cider/nrepl {:main-opts [“-m” “nrepl.cmdline” “--middleware” “[cider.nrepl/cider-middleware]“]}}}’ -Mdev:test:cider/nrepl
But same error happens.
Please advice, what I am doing wrong?damn it!
yes, it seems in source as well
let me try
yes, stupid typo
thank you so much!
@UK0810AQ2 you are my saver!
Glad I could help While you're profiling, make sure you have profiling events enabled if on Linux and that you have debug symbols installed
thanks, but i am on macos same applies?
Partially, consult the docs, you still need debug symbols and a few flags for good results
roger! thanks!
Does anyone here use ragtime for db migrations. Is there any way to force it to only run on one pod? We just had to deal with a conflict where all pods tried to write to the migrations table
Don't couple database migrations with process initialization. Make them part of your deploy pipeline, just prior to rolling out to pods
Can anyone explain the `:-` syntax in compojure sweet api? E.g.
(def app
(api
(GET "/hello" []
:query-params [name :- String]
(ok {:message (str "Hello, " name)}))))
To be on the same page - it's not syntax per se, it's just a keyword in Clojure.
I'm just guessing here, but it looks like it's used to specify the type of the name
parameter.
is that for type coercion?
sure seems like it https://github.com/metosin/compojure-api/wiki/Coercion
Thanks @U02N27RK69K. Do you know if the empty string in this ex is supposed to be a default value?
[name :- String ""]
I'm guessing a default value, yes, but you should try it out and see
stick a nonsense word in there and perform a request against it
another data point here https://github.com/metosin/compojure-api/blob/master/examples/coercion/src/example/data_spec.clj#L12
https://github.com/metosin/compojure-api/blob/master/examples/coercion/src/example/spec.clj#L19
Wow this stuff is ancient.
Oh this is work, I don't get a choice. :^)
Inside a unit test I want to verify that the response (a map) contains certain things, that are possibly deeply nested. Are there libraries that: • allow flexible projection of an existing map (something like the glom library for python) • assert equality between two maps in a test, and displays a visual diff of mismatches, preferably colorful
I just use https://clojuredocs.org/clojure.data/diff and look for [nil? nil? dont-care] as passing
there are lots of options for examining nested data structures: • https://github.com/redplanetlabs/specter • https://github.com/noprompt/meander • see the Data Transformation section: https://www.clojure-toolbox.com/ • lots more, but those are the ones that I've found useful. for diffing, there's also multiple options. I've used https://github.com/lambdaisland/deep-diff2
lein-difftest, too, if you use lein