Clojure: (with-out-str (doc catch)) returns "" - clojure

I wonder why this is.
finally and & also behave in this way.
Which other Clojure symbols have this behavior and why?

I believe that you have stumbled across a bug in Clojure's implementation of doc that affects &, catch, and finally. In the current doc implementation, these three are treated specially, and the associated expression appears to be missing a syntax quote.
Following is a mod to doc that adds the syntax quote and appears to work as intended. This function must be placed in the clojure.repl namespace.
(defmacro doc2
[name]
(if-let [special-name ('{& fn, catch try, finally, try} name)]
`(#'print-doc (#'special-doc '~special-name))
(cond
(special-doc-map name) `(#'print-doc (#'special-doc '~name))
(find-ns name) `(#'print-doc (#'namespace-doc (find-ns '~name)))
(resolve name) `(#'print-doc (meta (var ~name))))))
(doc catch) => { prints try doc and returns nil }
(doc2 catch) => { prints try doc and returns nil }
(with-out-str (doc catch)) => { prints try doc and returns "" }
(with-out-str (doc2 catch)) => "-------------------------\ntry\n (try expr* catch-clause* finally-clause?)\nSpecial Form\n catch-clause => (catch classname name expr*)\n finally-clause => (finally expr*)\n\n Catches and handles Java exceptions.\n\n Please see http://clojure.org/special_forms#try\n"
I'll chase this down on the Clojure bug tracker.

Related

Resolving a keyword into a Malli schema from the default registry in Clojure

How do I resolve a keyword to a schema from the default Malli registry? I seem unable to look up a value in the registry in order to walk it.
(def registry
(atom {}))
(defn register! [type ?schema]
(swap! registry assoc type ?schema))
;; Combine the default registry with our own mutable registry.
(mreg/set-default-registry!
(mreg/composite-registry
(mreg/fast-registry (malli/default-schemas))
(mreg/mutable-registry registry)))
(register! :db/kasse
[:map
[:id [:int {:primary-key true :db-generated true}]]
[:odlingsplats [:string {:foreign-key "odlingsplatser"}]]
[:diameter_m :int]
[:djup_m :int]
[:volym_m2 [:int {:db-generated true}]]])
(malli/walk
:db/kasse
(malli/schema-walker identity))
;; => :db/kasse
I've tried wrapping :db/kasse in different functions from malli but none seem to do the lookup and malli/-lookup is private. Just running (:db/kasse malli/default-registry) does not work either. Using malli/schema seems like the obvious choice but it seemingly has no effect.
(malli/walk
(malli/schema :db/kasse)
(malli/schema-walker identity))
;; => :db/kasse
Calling malli/deref was the answer:
(malli/walk
(malli/deref :db/kasse)
(malli/schema-walker identity))
;; => [:map [:id [:int {:primary-key true, :db-generated true}]] [:odlingsplats [:postgres/string {:foreign-key "odli\
ngsplatser"}]] [:diameter_m :int] [:djup_m :int] [:volym_m2 [:int {:db-generated true}]] [:namn {:optional true} [:po\
stgres/string {:db-generated true}]]]
Thank you to ikitommi at the Clojurians slack for providing the answer. He also provided an explanation as to why the library works this way:
The :db/kasse returned is a Malli Schema instance, it’s print output is just the form, so looks like keyword. It’s type is :malli.core/schema, which is the internal eager reference, like a Var in Clojure. If you want to get the schema behind it, you can m/deref it. But, calling m/validate on :db/kasse works too. the :malli.core/schema forwards the calls to the actual instance, like Var.

Testing Timbre log outputs with Midje

I am using Timbre as a logging library but I am having issues testing it with Midje. I've got the following method and all I'm trying to do is asserting that Will be printed is printed.
(defn init [level]
(timbre/merge-config! {:output-fn my-output-fn})
(timbre/set-level! level)
(timbre/info "Will be printed")
(timbre/debug "Won't be printed"))
By wrapping (timbre/default-output-fn) around a function of my own my-output-fn, I am able to assert that only 1 out of 2 logs are printed, which is true:
(fact "print info but not debug"
(core/init :info) => nil
(provided
(core/my-output-fn anything) => irrelevant :times 1))
However I would like to make sure that the message being printed is Will be printed. I can't find any way of doing this, what would you do?
I am doing experiments in the following project https://github.com/stephanebruckert/timbre-midje
It is possible to validate the input of a function using Midje's as-checker prerequisite.
When you print the data that come into timbre/default-output-fn (I discovered this via your output-fn) you see it has the following structure:
{:hash_ #delay[{:status :pending, :val nil} 0x5ed805b1], :instant #inst "2016-10-14T17:07:16.779-00:00", :config {:level :info, ....
So the log-level is available in data. With as-checker the log level can be validated as follows:
(fact "print info but not debug"
(core/init :info) => nil
(provided
(timbre/default-output-fn anything ; opts is first argument
(as-checker (fn [data]
(= (-> data :config :level) ; get log level
:info)))) ; validate that it is info
=> anything :times 1)
(provided
(timbre/default-output-fn anything
(as-checker (fn [data]
(= (-> data :config :level)
:debug))))
=> anything :times 0))
Now, you wanted to check the content of the message. Not only the log level.
The actual message is not available in the opts or data passed toward default-output-fn. Looking around in the the Timbre code I saw it is available in a private function vargs->margs that takes an ?err, a msg-type and vargs. The vargs contain the message (in your case what comes in is for example :auto :p ["The message"]).
Via the as-checker approach the messages can be validated follows:
(fact "print Will be printed, not Won't be printed"
(core/init :info) => nil
(provided
(#'timbre/vargs->margs anything anything ["Will be printed"]) => {} :times 1)
(provided
(#'timbre/vargs->margs anything anything ["Won't be printed"]) => {} :times 0) )
Note that vargs->margs has to return a map, otherwise Timbre throws an exception in a later function.
This way it is validated that "Will be printed" is printed once, and "Won't be printed" is never printed.
#ErwinRooijakkers' idea worked but #ptaoussanis on Github has a good reason not to do it.
Please note that timbre/vargs->margs is private, and an implementation
detail. Its behaviour can change at any time without notice, would
strongly recommend not depending on it in any way.
It'd be possible to use a custom appender that sends output somewhere that are handy for your tests to analyse. You could setup these appenders as part of your test setup, and/or use something like timbre/with-config for the appropriate test calls.
So we can add an appender that passes the parameters to check (level message) to a stub.
core.clj
(defn init
([level]
(init level {}))
([level config]
(timbre/merge-config! config)
(timbre/set-level! level)
(timbre/info "will be printed")
(timbre/debug "won't be printed")))
core_test.clj
(:require [timbre-midje.core :as core]
[midje.sweet :refer :all]))
(defn log-stub [level message])
(def log-stub-appender
{:appenders
{:test-appender
{:enabled? true
:fn (fn [data] (log-stub (:level data) (:vargs data)))}}})
(fact "print info but not debug"
(core/init :info log-stub-appender) => nil
(provided
(log-stub :info ["will be printed"]) => irrelevant :times 1
(log-stub :debug ["won't be printed"]) => irrelevant :times 0))

Cannot use defroutes macro from compojure

When running this code :
(:use 'compojure.core)
(keys (ns-publics 'compojure.core))
(defroutes app-routes
(GET "/" [] "Hello World")
(route/resources "/")
(route/not-found "Not Found"))
I got this message:
CompilerException java.lang.RuntimeException: Unable to resolve symbol: defroutes in this context, compiling:(restful_clojure\routes.clj:5:1)
but when I run:
(keys (ns-publics 'compojure.core))
it shows that macro is defined:
(defroutes PUT POST routing routes make-route let-routes DELETE ANY let-request GET HEAD PATCH context OPTIONS)
Clojure has methods require, import, refer, and use. These are for working with different namespaces.
:use is a Keyword, which can behave like a function (in your example it should return nil), but does not do what you want.
The confusion likely arises from the fact that inside the ns macro, you can 'embed' the behavior of these functions using the corresponding keywords.
For more reading on namespaces, see this link.

Dynamic handler update in Clojure Ring/Compojure REPL

I've created a new Compojure Leiningen project using lein new compojure test. Web server is run by lein repl and then
user=> (use 'ring.adapter.jetty)
user=> (run-jetty test.handler/app {:port 3000})
Routes and app handler specification is trivial:
(defroutes app-routes
(GET "/*.do" [] "Dynamic page")
(route/not-found "Not Found"))
(def app
(wrap-defaults app-routes site-defaults))
Now, after changing anything in app-routes definition (e.g. changing "Dynamic page" text to anything else, or modifying URI matching string), i do not get the updated text/routes in the browser. But, when changing app-routes definition slightly to
(defn dynfn [] "Dynamic page fn")
(defroutes app-routes
(GET "/*.do" [] (dynfn))
(route/not-found "Not Found"))
i do get dynamic updates when changing the return value of dynfn. Also, following the advice from this article and modifying the app definition to
(def app
(wrap-defaults #'app-routes site-defaults))
(note the #' that transparently creates a var for app-routes) also helps!
Why is that so? Is there any other way one could get a truly dynamic behaviour in defroutes?
Thanks!
#'app-routes is a reader macro that expands to (var app-routes). When a var is used as if it were a function, it is dereferenced anew on each invocation, and then the value returned by that deref is called.
If you were to supply app-routes as the argument, the compiler would give the dereferenced value to wrap-defaults, and when the var is updated, the previous value is not changed, so changing the var does not change the behavior of app.
The following repl transcript might be instructive:
user=> (defn foo [] "original")
#'user/foo
user=> (defn caller [f] #(f))
#'user/caller
user=> (def call-foo-value (caller foo))
#'user/call-foo-value
user=> (call-foo-value)
"original"
user=> (def call-foo-var (caller #'foo))
#'user/call-foo-var
user=> (call-foo-var)
"original"
user=> (defn foo [] "changed")
#'user/foo
user=> (call-foo-value)
"original"
user=> (call-foo-var)
"changed"

NPE in clojure.lang.Reflector.invokeInstanceMethod only in some situations

I'm experiencing a strange problem with Java interop. I wrote a small specialized wrapper around the BDB JE API. When I'm in the repl (cider-repl) everything works fine: I can open the database, add entries, etc. But if I call the add-record function from another function in my app I get an NPE,
NullPointerException clojure.lang.Reflector.invokeInstanceMethod (Reflector.java:26)
I'm starting to think I'm losing my mind. This opens the database:
(defn opendb [envpath dbname]
(let [envconf (.setAllowCreate (EnvironmentConfig.) true)
env (Environment. (ensure-directory envpath) envconf)
dbconf (-> (DatabaseConfig.) (.setAllowCreate true) (.setDeferredWrite true))
database (.openDatabase env nil dbname dbconf)]
{:environment env :database database}))
Here is add-record:
(defn add-record [dbm k v]
(let [key (DatabaseEntry. (.getBytes k "UTF-8"))
value (DatabaseEntry. (.getBytes v "UTF-8"))]
(.put (:database dbm) nil key value)))
There really isn't anything special going on here. The usage where this yields the NPE is similar to
(let [cache (bdb/opendb "local-cache" "subject-map")]
;; do stuff
(doseq [node (function "that returns a sequence of maps")]
(bdb/add-record cache (:foo node) (:bar node)))
(bdb/closedb cache))
I've added prnS inside bb/add-record and all the values are non-nil, yet I still get the NPE.
Something subtle is going on here, and it's eluding me. Anyone have an idea?
Thanks inadvance.
EDIT: here's the full stack trace:
Exception in thread "main" java.lang.NullPointerException
at clojure.lang.Reflector.invokeInstanceMethod(Reflector.java:26)
at sterling.bdbje$add_record.invoke(bdbje.clj:33)
at sterling.loaders$load_subject_batch.invoke(loaders.clj:214)
at sterling.loaders$load_subject_headings.invoke(loaders.clj:224)
at sterling.loaders$_main.doInvoke(loaders.clj:257)
at clojure.lang.RestFn.applyTo(RestFn.java:137)
at sterling.loaders.main(Unknown Source)
As I said, this makes no sense to me, but is completely reproducible.