I just started on my first clojure project using lein, the code here:
(ns fileops.core
(:use
[clojure.core :only (slurp)]
[clojure-csv.core :only (parse-csv)]
[fileops.core]))
(defn -main
"I don't do a whole lot ... yet."
[& args]
(read-file "sample.csv"))
(defn read-file
"open and read the csv file"
[fname]
(with-open [file (clojure.java.io/reader fname)]
(parse-csv (slurp fname))))
I tried to run this using "lein run" but I keep getting this error:
Caused by: java.lang.RuntimeException: Unable to resolve symbol: read-file in this context
at clojure.lang.Util.runtimeException(Util.java:219)
at clojure.lang.Compiler.resolveIn(Compiler.java:6874)
at clojure.lang.Compiler.resolve(Compiler.java:6818)
at clojure.lang.Compiler.analyzeSymbol(Compiler.java:6779)
at clojure.lang.Compiler.analyze(Compiler.java:6343)
... 52 more
What am I doing wrong?
Explanations: Clojure did not find any existing namespace named a.b.c, then searched the classpath for a lib that would define it, eventualling failing with the above Exception. The cause may vary:
Note that the error message (‘ClassNotFoundException’) is particularly confusing in this case: the reason is that the Clojure compiler, having found no loaded namespace named clojure.set , is trying to interpret clojure.set as a Java class. The solution is to make sure the clojure.set lib has been loaded.
Maybe you forgot to define my-nonexistent-name in the REPL (using e.g def or defn ): this could happen if you wrote a (def my-nonexistent-name …) in your code file but forgot to evaluate it in the REPL. Maybe you defined my-non-existent-name, but in another namespace.
You have used only slurp from clojure core, meaning that every other core function is now unavailable to you :) Try changing your ns
to use :require
instead of :use
, as this is more idiomatic.
One thing to note is that order does matter in clojure, so if you don't declare a function at the top of your file, as in C and some other languages, the earlier functions will not be able to make reference to them. This is what was causing your error before and is why I like to define my -main
function at the bottom. It's a matter of style.
Another thing is that your -main
function is taking variable args right now and not using them. In Clojure it is idiomatic to use _
to refer to a parameter that doesn't get used. You could use & _
to avoid error messages, for when the user passes in unnecessary args, but I would just have the -main function parameterless from the start. This is because nothing needs to be provided to main when you run the program, and errors do make debugging easier. It is good to know what is getting used and where. The sample.csv
file is already provided and is having read-file
called on it, so the program should run if your read-file
function is correct and the sample.csv
file is in the proper location.
Regarding your -main
function, it would be nice to put a little test in there to see if it executes properly when you run it, so I changed it to print out the contents of the csv file onto your console. This way of printing from a file is efficient and worth studying in its own right.
Finally, Make sure you include clojure-csv.core
in your project.clj
file.
core.clj:
(ns fileops.core
(:require
[clojure-csv.core :refer [parse-csv]]))
(defn read-file
"open and read the csv file"
[fname]
(with-open [file (clojure.java.io/reader fname)]
(parse-csv (slurp fname))))
(defn -main []
(println (clojure.string/join "\n" (read-file "resources/test.csv"))))
project.clj:
...
:dependencies [[org.clojure/clojure "1.5.1"]
[clojure-csv/clojure-csv "2.0.1"]
...]
:main fileops.core
You need to declare fileops.core as :main, as shown above. This tells Leiningen what function to execute when you enter lein run
. Very important and tricky stuff.
So now make sure you are in the root of your project directory and at the terminal, run the following:
lein clean
lein deps
lein run
Good luck!
Further reading:
8th light blog on name-spaces
flying machine studios explanation of lein run
read-file should be before main in your source OR you should put before -main a declare cause like that:
(declare read-file)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With