Clojure - (read-string String calling function - clojure

I've got the following in a clojure file:
(ns helloworld
(:gen-class
:main -main))
(defn hello-world-fn []
(println "Hello World"))
(defn -main [& args]
(eval (read-string "(hello-world-fn)")))
and I'm running it with
lein run helloworld
and I'm getting the following error:
Exception in thread "main" java.lang.RuntimeException: Unable to resolve symbol:
helloworld in this context, compiling:(helloworld.clj:12)
I have a feeling I need to do something with ns-resolve or resolve but I haven't had any success. I've tried the following in the main function:
(let [call-string (read-string "(hello-world-fn)")
func (resolve (symbol (first call-string)))
args (rest call-string)]
(apply func args))
Without success.
Can someone (a) point me in the right direction; and (b) explain precisely what is going on in the Clojure reader when this occurs?

Try to see what the actual namespace is inside your -main.
(defn -main [& args]
(prn *ns*)
(eval (read-string "(hello-world-fn)")))
It outputs #<Namespace user> before bombing out with the exception. This hints that execution of programs with lein run starts out in the user namespace, which obviously does not contain the mapping for your hello-world-fn symbol. You'll need to explicitly qualify it.
(defn -main [& args]
(eval (read-string "(helloworld/hello-world-fn)")))

You can solve your challenge, in a very elegant way, using macros. In fact, you can write a macro that mimics eval.
(defmacro my-eval [s] `~(read-string s))
(my-eval "(hello-world-fn)")); "Hello World"
It works better that eval because the symbol resolution of s occurs in the context that calls my-eval. Thanks to #Matthias Benkard for the clarifications.
You can read about macros and their syntax in http://clojure.org/reader

Related

Clojure load-file on repl and call -main with arguments

I've done some coding in clojure inside core.clj which have a -main method that can take 0 or more arguments:
(defn -main
"dequeue function"
[& args]
I'm loading this clj file with:
(load-file "src/exercise/core.clj")
And then i'm trying to learn how to call this within repl in order to develop core_test.clj (if there is any tips about how to develop this auto tests, please give me some hints as well). What I'm trying to do now is:
(-main "resources\\sample-input.json" "a")
But this is printing "Arguments 0" which is a message that I told the code to print just to see how many arguments are being passed with
(println "Arguments" (count *command-line-args*))
How am I suposed to do this?
Thanks!
i'm trying to learn how to call this within repl in order to develop core_test.clj
Usually you'd write other functions that are called from -main and test those rather than the app's entry point -main.
But you should be able to call -main like any other function. I have a src/sandbox/main.clj file:
(ns sandbox.main)
(defn -main [& args]
(prn args))
Starting a REPL in the project folder, I can call -main like this:
(use 'sandbox.main) ;; (load-file "src/sandbox/main.clj") also works
=> nil
(in-ns 'sandbox.main)
=> #object[clojure.lang.Namespace 0x67ccce04 "sandbox.main"]
(-main "some" "args")
;; ("some" "args")
=> nil
There's a key difference in my example though: it's printing -main's args binding; *command-line-args* is nil because you're not running the code from the command line with args, you're running it from a REPL.
Regardless, it's probably a better idea to use an existing library to work with CLI args rather than *command-line-args* directly.

lein test throws NPE for function using "resolve"; works in REPL

lein test throws a NullPointerException when testing a function that uses (resolve (symbol "a-fn")) to return function a-fn. The test runs fine from the REPL.
I have not been able to find a way to resolve a-fn in the testing suite for leiningen, if that is indeed the issue.
I created a Leiningen project called my-resolve by lein new my-resolve and added two functions and tests for them:
src/my_resolve/core.clj:
(ns my-resolve.core)
(defn a-fn [] "From a-fn")
(defn my-resolve [] (resolve (symbol "a-fn")))
test/my_resolve/core_test.clj:
(ns my-resolve.core-test
(:require [clojure.test :refer :all]
[my-resolve.core :refer :all]))
;; Passes
(deftest a-fn-test
(testing "a-fn"
(is (= (a-fn)
"From a-fn"))))
;; my-resolve-test behaves correctly in the REPL (the test passes,
;; returns nil) but throws a NullPointerException when called from
;; lein test.
(deftest my-resolve-test
(testing "my-resolve"
(is (= ((my-resolve))
"From a-fn"))))
Thank you.
resolve delegates to ns-resolve using the dynamically bound *ns*, which at the point of the call in my-resolve.core/my-resolve will be different depending on what namespace it is being called from:
user=> (doc resolve)
-------------------------
clojure.core/resolve
([sym] [env sym])
same as (ns-resolve *ns* symbol) or (ns-resolve *ns* &env symbol)
I assume that in the REPL you are calling my-resolve when in the my-resolve.core ns. When lein test executes the test in my-resolve.core-test, *ns* is dynamically bound to (the-ns 'user) and that ns (most likely) does not contain a binding to my-resolve.

Why does lein run hang?

I have created a Leiningen project for Exercise 2 from here. My code looks like this:
(ns random-quotes.core
(:require [clojure.string :as str])
(:gen-class))
(defn word-count [s]
(frequencies (str/split (first (str/split s #"\n")) #"\s")))
(def quote-url "http://www.braveclojure.com/random-quote")
(def total-word-count (atom {}))
(defn update-word-count []
(future
(swap! total-word-count
(partial merge-with +)
(word-count (slurp quote-url)))))
(defn quote-word-count [n]
(doseq [quote-future (doall (repeatedly n update-word-count))]
#quote-future)
#total-word-count)
(defn -main [n]
(doseq [entry (sort-by val (quote-word-count (bigdec n)))]
(println entry)))
All pretty straightforward. When I run, e.g., (-main 5) in lein repl, it runs, prints, and returns as expected. However, when I try lein run 5 instead, it runs and prints but never exits, so I am forced to use Ctrl+C to get my terminal back.
Any idea why this happens?
Clojure has a thread pool that it keeps running for use by the agents. Because those threads are still alive, the JVM can't tell that you're program is done. It's just sitting there waiting for the agents to exit. You can make them finish by calling (shutdown-agents) at the end of your program as described here. Futures use agents.
clojure.core/future-call calls an agent like this:
(let [f (binding-conveyor-fn f)
fut (.submit clojure.lang.Agent/soloExecutor ^Callable f)]
which actually starts your code running. You would not be the only one to voice some criticism of this, and we all hope a more elegant solution is found.

How to check whether Clojure code is being evaluated inside a REPL?

I would like to format my logs differently depending on whether my code is being run from a REPL or if I'm running the compiled jar.
Is there any simple way to do this? I was thinking maybe Leiningen leaves a trace somewhere when running the REPL.
(defn current-stack-trace []
(.getStackTrace (Thread/currentThread)))
(defn is-repl-stack-element [stack-element]
(and (= "clojure.main$repl" (.getClassName stack-element))
(= "doInvoke" (.getMethodName stack-element))))
(defn is-in-repl []
(some is-repl-stack-element (current-stack-trace)))
(defn my-log [msg]
(if (is-in-repl)
(prn (str "RUNNING IN REPL : " msg))
(prn msg)))

I would like to run load-file in a sandboxed namespace in clojure

I'm new to Clojure and for fun/education I'm writing a generic migration framework for lein. One thing this system has to do is read a clojure file from the disk, then run either the up function, or the down function. I figure this file should probably be evaluated in a temporary namespace but I'm having trouble getting that to work. Here's what I have so far:
(def user-namespace (create-ns 'leiningen.generic-migrate.user-eval))
(defn load-migration-file [file]
(binding [*ns* user-namespace]
(load-file (.getAbsolutePath file))
(keys (ns-publics *ns*))))
This gives me the error:
Unable to resolve symbol: defn in this context
My question is, what's the best approach for using load-file, then running a defined function, without risk of someone overwriting stuff in my namespace?
(defmacro with-ns
"Evaluates body in another namespace. ns is either a namespace
object or a symbol. This makes it possible to define functions in
namespaces other than the current one."
[ns & body]
`(binding [*ns* (the-ns ~ns)]
~#(map (fn [form] `(eval '~form)) body)))
(defmacro with-temp-ns
"Evaluates body in an anonymous namespace, which is then immediately
removed. The temporary namespace will 'refer' clojure.core."
[& body]
`(try
(create-ns 'sym#)
(let [result# (with-ns 'sym#
(clojure.core/refer-clojure)
~#body)]
result#)
(finally (remove-ns 'sym#))))