Nil? resolve variable returns nil after def - clojure

I'm new to Clojure so this might be obvious.
(println (nil? (resolve 'x)))
(def x 1)
(println (nil? (resolve 'x)))
This prints out
true
true
Why doesn't the second println output false?
According to the examples on ClojureDocs, shouldn't this be the case?
EDIT:
I'm not running this through REPL.
This is how I got there:
Create a project via lein new testing.
After modifications to core.clj, it looks like this:
(ns testing.core
(:gen-class))
(defn -main
[& args]
(println (nil? (resolve 'x)))
(def x 1)
(println (nil? (resolve 'x)))
)
When ran through lein run, output is:
true
true

When I evaluate those expressions in a Clojure REPL, I get true for the first one, and false for the second one. How you are you starting the Clojure REPL? What version of Clojure are you using? Can you reproduce this consistently?

(resolve 'x) try to get a Var named by (bound to) the x symbol. If this Var does not exist, it should return nil. So your assumptions are correct.
If you are coding with a live REPL, remember that code you evaluate stays in memory until you replace it by a new version or manually undefine it.
Here is a visual REPL session from my side showing the correct behavior:

There is something strange about your environment:
~/expr/demo > lein repl
demo.core=> (resolve 'x)
nil
demo.core=> (resolve 'x)
nil
demo.core=> (resolve 'x)
nil
demo.core=> (resolve 'x)
nil
demo.core=> (def x 1)
#'demo.core/x
demo.core=> (resolve 'x)
#'demo.core/x

Try running the following program instead, and read the output carefully. Note that the doc string for the function 'resolve' says that it resolves the symbol in the namespace that is the current value of *ns*, and that is a "dynamic var", which according to the output of the program shown below, is equal to the 'user' namespace by default, different than the namespace where the function is defined, which is the namespace where 'x' is 'def'd.
(ns testing.core
(:gen-class))
(defn -main
[& args]
(println)
(println "before (def x 1)")
(println "*ns*=" *ns*)
(println "(resolve 'x)=" (resolve 'x))
(println "(resolve 'user/x)=" (resolve 'user/x))
(binding [*ns* 'testing.core]
(println "*ns*=" *ns*)
(println "(resolve 'x)=" (resolve 'x))
(println "(resolve 'user/x)=" (resolve 'user/x)))
(def x 1)
(println)
(println "after (def x 1)")
(println "*ns*=" *ns*)
(println "(resolve 'x)=" (resolve 'x))
(println "(resolve 'user/x)=" (resolve 'user/x))
(binding [*ns* 'testing.core]
(println "*ns*=" *ns*)
(println "(resolve 'x)=" (resolve 'x))
(println "(resolve 'user/x)=" (resolve 'user/x))))
Output on my system:
before (def x 1)
*ns*= #object[clojure.lang.Namespace 0x524f3b3a user]
(resolve 'x)= nil
(resolve 'user/x)= nil
*ns*= testing.core
(resolve 'x)= #'testing.core/x
(resolve 'user/x)= nil
after (def x 1)
*ns*= #object[clojure.lang.Namespace 0x524f3b3a user]
(resolve 'x)= nil
(resolve 'user/x)= nil
*ns*= testing.core
(resolve 'x)= #'testing.core/x
(resolve 'user/x)= nil

Related

Creating a Ruby-like `binding.pry` macro in Clojure

I've been struggling to create a macro that'll allow me to dynamically bind whatever is in the &env into a binding form and then delegate to a pry like function to open a REPL that can see those bound &env symbols.
My simplistic pry func, which works as expected
(defn pry []
(print (str "pry(" *ns* ")> "))
(flush)
(let [expr (read)]
(when-not (= expr :exit)
(println (eval expr))
(recur))))
Using the pry func:
clojure-noob.core=> (def a 1)
#'clojure-noob.core/a
clojure-noob.core=> (pry)
pry(clojure-noob.core)> (+ a 1)
2
pry(clojure-noob.core)> :exit
nil
clojure-noob.core=>
My attempt at creating a dynamic invocation of binding:
(defmacro binding-pry []
(let [ks (keys &env)]
`(let [ks# '~ks
vs# [~#ks]
bs# (vec (interleave ks# vs#))]
(binding bs# (pry)))))
However, this fails because the inner symbol bs# is not expanded to an actual vector but instead is the generated symbol and binding tosses a clojure.core/binding requires a vector for its binding exception.
clojure-noob.core=> (let [a 1 b 2] (binding-pry))
Syntax error macroexpanding clojure.core/binding at (/tmp/form-init14332359378145135257.clj:1:16).
clojure.core/binding requires a vector for its binding in clojure-noob.core:
clojure-noob.core=>
The code quoted form with a debug print, the bs# symbol is resolved when printing but I don't know how to make it resolve to a vector when constructing the binding form.
(defmacro binding-pry []
(let [ks (keys &env)]
`(let [ks# '~ks
vs# [~#ks]
bs# (vec (interleave ks# vs#))]
(println bs#)
`(binding bs# (pry)))))
clojure-noob.core=> (let [a 1 b 2] (binding-pry))
[a 1 b 2]
(clojure.core/binding clojure-noob.core/bs__2464__auto__ (clojure-noob.core/pry))
clojure-noob.core=>
I'm very confident I'm tackling this incorrectly but I don't see another approach.
The Joy of Clojure demonstrates a break macro that does this already. I can't reproduce its source here, because it's EPL and not CC. But you can see its source at https://github.com/joyofclojure/book-source/blob/b76ef15/first-edition/src/joy/breakpoint.clj. It refers to a contextual-eval function as well: https://github.com/joyofclojure/book-source/blob/b76ef15/first-edition/src/joy/macros.clj#L4-L7.
A first step towards improving your attempt could be writing:
(defmacro binding-pry []
(let [ks (keys &env)]
`(binding [~#(interleave ks ks)] (pry))))
This still doesn't work because binding expects that the symbols can be resolved to existing dynamic vars. To tackle this problem you could make binding-pry introduce such vars as shown below:
(defmacro binding-pry []
(let [ks (keys &env)]
`(do
~#(map (fn [k] `(def ~(with-meta k {:dynamic true}))) ks)
(binding [~#(interleave ks ks)] (pry)))))
But this can have undesirable side-effects, like polluting the namespace with new var-names or making existing vars dynamic. So I would prefer an approach like the one mentioned in amalloy's answer but with a better implementation of eval-in-context (see my comment there).
To write a self-contained answer based on your pry function, let's first define eval-in which evaluates a form in an environment:
(defn eval-in [env form]
(apply
(eval `(fn* [~#(keys env)] ~form))
(vals env)))
Then let's modify pry to take an environment as an argument and use eval-in instead of eval:
(defn pry [env]
(let [prompt (str "pry(" *ns* ")> ")]
(loop []
(print prompt)
(flush)
(let [expr (read)]
(when-not (= expr :exit)
(println (eval-in env expr))
(recur))))))
An equivalent, less primitive version could be:
(defn pry [env]
(->> (repeatedly (let [prompt (str "pry(" *ns* ")> ")]
#(do (print prompt) (flush) (read))))
(take-while (partial not= :exit))
(run! (comp println (partial eval-in env)))))
Now we can define binding-pry as follows:
(defmacro binding-pry []
`(pry ~(into {}
(map (juxt (partial list 'quote) identity))
(keys &env))))
Finally, here is a direct/"spaghetti" implementation of binding-pry:
(defmacro binding-pry []
(let [ks (keys &env)]
`(->> (repeatedly (let* [prompt# (str "pry(" *ns* ")> ")]
#(do (print prompt#) (flush) (read))))
(take-while (partial not= :exit))
(run! (comp println
#((eval `(fn* [~~#(map (partial list 'quote) ks)] ~%))
~#ks))))))

How to extend and redefine a clojure macro?

I want to extend and redefine a clojure.core macro. For example, how can I redefine clojure.core/defn while using the original definition?
This is a bit tricky, but by aliasing the macro in clojure.core this is possible.
Open the repl and follow the steps below.
➜ ~ clj
Clojure 1.9.0
First alias clojure.core/defn to something else:
user=> (in-ns 'clojure.core)
#object[clojure.lang.Namespace 0x48e92c5c "clojure.core"]
clojure.core=> (defmacro defn-holder [])
#'clojure.core/defn-holder
clojure.core=> (alter-var-root #'defn-holder (constantly (var-get #'defn)))
#object[clojure.core$defn__5154 0xd3957fe "clojure.core$defn__5154#d3957fe"]
Next, create a new defn macro that uses the alias definition
clojure.core=> (in-ns 'user)
#object[clojure.lang.Namespace 0x64ba3208 "user"]
user=> (defmacro defn [& args] `(do (println "aliased version")(clojure.core/defn-holder ~#args)))
WARNING: defn already refers to: #'clojure.core/defn in namespace: user, being replaced by: #'user/defn
#'user/defn
user=> (defn foo [a])
aliased version
#'user/foo
user=> (foo 1)
nil
However it doesn't work for all namespaces yet:
user=> (ns bar)
nil
bar=> (defn foo [a])
#'bar/foo
We need to redefine defn in clojure.core with our new definition:
bar=> (in-ns 'clojure.core)
#object[clojure.lang.Namespace 0x48e92c5c "clojure.core"]
clojure.core=> (alter-var-root #'defn (constantly (var-get #'user/defn)))
#object[user$defn 0x37052337 "user$defn#37052337"]
Now it works:
clojure.core=> (in-ns 'bar)
#object[clojure.lang.Namespace 0x37efd131 "bar"]
bar=> (defn foo [a])
aliased version
#'bar/foo

Using with-redefs inside a doseq

I have a Ring handler which uses several functions to build the response. If any of these functions throw an exception, it should be caught so a custom response body can be written before returning a 500.
I'm writing the unit test for the handler, and I want to ensure that an exception thrown by any of these functions will be handled as described above. My instinct was to use with-redefs inside a doseq:
(doseq [f [ns1/fn1 ns1/fn2 ns2/fn1]]
(with-redefs [f (fn [& args] (throw (RuntimeException. "fail!"))]
(let [resp (app (request :get "/foo")))))]
(is (= (:status resp) 500))
(is (= (:body resp) "Something went wrong")))))
Of course, given that with-redefs wants to change the root bindings of vars, it is treating f as a symbol. Is there any way to get it to rebind the var referred to by f? I suspect that I'm going to need a macro to accomplish this, but I'm hoping that someone can come up with a clever solution.
with-redefs is just sugar over repeated calls to alter-var-root, so you can just write the desugared form yourself, something like:
(doseq [v [#'ns1/fn1 #'ns1/fn2 #'ns2/fn1]]
(let [old #v]
(try
(alter-var-root v (constantly (fn [& args]
(throw (RuntimeException. "fail!")))))
(let [resp (app (request :get "/foo")))
(is (= (:status resp) 500))
(is (= (:body resp) "Something went wrong")))
(finally (alter-var-root v (constantly old))))))
Following on from amalloy's great answer, here's a utility function that I wrote to use in my tests:
(defn with-mocks
"Iterates through a list of functions to-mock, rebinding each to mock-fn, and calls
test-fn with the optional test-args.
Example:
(defn foobar [a b]
(try (+ (foo a) (bar b))
(catch Exception _ 1)))
(deftest test-foobar
(testing \"Exceptions are handled\"
(with-mocks
[#'foo #'bar]
(fn [& _] (throw (RuntimeException. \"\")))
(fn [a b] (is (= 1 (foobar a b)))) 1 2)))"
[to-mock mock-fn test-fn & test-args]
(doseq [f to-mock]
(let [real-fn #f]
(try
(alter-var-root f (constantly mock-fn))
(apply test-fn test-args)
(finally
(alter-var-root f (constantly real-fn)))))))

How can I pretty print a quoted list in clojure?

Given a list like:
(quote (do (println "Hello") (println "Goodbye")))
: how can I turn this into a nicely formatted string which will output something like:
(do
(println "Hello")
(println "Goodbye")
)
Use clojure.pprint/write with clojure.pprint/code-dispatch:
(clojure.pprint/write '(do (println "Hello") (println "Goodbye"))
:dispatch clojure.pprint/code-dispatch)
For that small amount of code you won't get new-lines. But a call like this
(clojure.pprint/write '(do (println "Hello") (println "Goodbye") (println "Hey, you left me out!"))
:dispatch clojure.pprint/code-dispatch)
Returns
=> (do
(println "Hello")
(println "Goodbye")
(println "Hey, you left me out!"))
To catch that as a string wrap the call in (with-out-str ...)
As a significantly more performant alternative to clojure.pprint, you might want to try Brandon Bloom's fipp:
;; add [fipp "0.4.0"] to :dependencies
(require '[fipp.edn :as fipp])
(fipp/pprint '(do (println :foo) (println :bar) (println :quux))
{:width 30}) ; force wrapping despite small size of data
;; printed output:
(do
(println :foo)
(println :bar)
(println :quux))
Unfortunately, Fipp does not yet support code-dispatch.

Clojure: namespace and -main

I'm trying to understand the -main and its namespace settings. The default namespace in a -main function seems to be "user", but function defined "above" the main function, in the same file, can be called. Are they referred? I was running this to find out:
(ns ack.doodle)
(defn fo [] "bar")
(defn -main [& args]
(println (fo)) ;; bar
(println *ns*) ;; #<Namespace user>
(println (get (ns-refers *ns*) 'sorted-map)) ;; #'clojure.core/sorted-map
(println (get (ns-refers *ns*) 'fo)) ;; nil
(println (get (ns-map *ns*) 'fo)) ;; nil
(println (get (ns-publics *ns*) 'fo)) ;; nil
(println (get (ns-interns *ns*) 'fo)) ;; nil
(println (get (ns-aliases *ns*) 'fo)) ;; nil
(println (ns-resolve *ns* 'fo))) ;; nil
The call (fo) succeeds, yet apparently the symbol 'fo is not known in the current namespace *ns*. What's going on?
This problem hit me when trying to pass the name of some function, along with some arguments, as command line arguments to -main.
steps to reproduce
paste above code in a file ./src/ack/doodle.clj
create ./project.clj with these contents:
(defproject ack "1" :main ack.doodle)
run it:
lein run
It looks like leiningen runs (-main) by calling it from user namespace like that: (ack.doodle/-main). Thus *ns* is bound to the user namespace.
Try running lein repl in your project root. Then run (-main) and see what happens. :)
Didn't I answer this for you last night in #clojure? If there's something unsatisfying about the answer, you'll have to clarify your question.