The following code seems to run fine. I see it print "inside main" but I don't see a dataset being printed. small-sample.csv contains several lines like below. What is the correct way to print a dataset?
I modified the code and now see that the program throws an exception. If I remove the print, I don't get an exception but I see no output. Not sure what I am doing wrong?
;;small-sample.csv file
Gomez,Addams,father
Morticia,Addams,mother
Pugsley,Addams,brother
...
(use 'incanter.core
'incanter.io)
(ns getting-data.core
(:require [incanter.core :as incanter]) (:require [incanter.io :as io])
)
(defn -main
"Command-line entry point."
[& raw-args]
(try
(println "inside main")
(print((io/read-dataset "data/small-sample.csv")))
(catch Exception e (prn "in catch1"))))
)
I think you should simply remove the parenthesis in io/read-dataset, like this:
(print (io/read-dataset "data/small-sample.csv"))
from the docs:
Returns a dataset read from a file or a URL.
The extra parenthesis tries to evaluate the data-set
Related
I just started learning Clojure and I have my own Clojure script but it's not returning the output that I am hoping for (Hello World). Here is my code:
(ns com.playground.core
(:gen-class))
(defn -main
[]
((defn CHEESE
[]
(str "Hello World"))
(CHEESE)))
This is the output that I get in the REPL:
clj꞉com.playground.core꞉>
#'com.playground.core/-main
I want to see Hello World in the output.
You have a double parentheses there. Try this:
(defn -main
[]
(defn CHEESE
[]
(str "Hello World"))
(CHEESE))
Of course your MUST call -main, otherwise you'll see nothing:
(defn -main
[]
(defn CHEESE
[]
(str "Hello World"))
(CHEESE))
=> #'com.playground.core/-main
(-main)
=> "Hello World"
I see your define a function inside another function. You should use let or letfn for this purpose.
Starting a REPL for the project does not run -main. Running your program produces the following:
Execution error (ArityException) at com.playground.core/-main (core.clj:6).
Wrong number of args (1) passed to: com.playground.core/-main/CHEESE--177
What is happening?
The defn form creates and registers a function under the name
CHEESE in the com.playground.core namespace.
The defn form returns the created var, which evaluates to the
function.
The containing ((defn ...) (CHEESE)) form applies the CHEESE function to
(CHEESE), the result of evaluating the CHEESE function without
arguments,
... which is the string "Hello World".
It doesn't matter what the argument is, because CHEESE has no arity 1 invocation: you can't apply it to any argument.
You can get the same (bad) effect more simply by pulling the defn for CHEESE out of -main. While we're at it, let's drop the str, which has no effect:
(defn CHEESE []
"Hello World")
(defn -main []
(CHEESE (CHEESE)))
Execution error (ArityException) at com.playground.core/-main (core.clj:8).
Wrong number of args (1) passed to: com.playground.core/CHEESE
To put it right, we simply drop the (CHEESE)argument:
(defn -main []
(CHEESE))
producing ...
Process finished with exit code 0
No returned value, but at least it ran. But if we evaluate (-main) in a REPL, ...
(-main)
=> "Hello World"
There.
Actually, It's not exactly wrong.
This return is the "return of declaration".
For example, you defined a -main in the com.playground.core namespace.
The return is the symbol of this declaration #'com.playground.core/-main
To print the Hello world message you need to call the function CHEESE after the declaration.
So... about double parenthesis, it's not good, but not impact hehe.
Another point is the function name, it's not good too. Consider using kebab-case.
You also consider keeping the function declaration more explicitly. Something like that;
(ns com.playground.core
(:gen-class))
(defn CHEESE [] (str "Hello World"))
(defn -main []
(CHEESE))
But also did it you're not printing the Hello world. Your only declaring a function (CHEESE) that returns a String type.
To print, you need to call a print function.
(ns com.playground.core
(:gen-class))
(defn hello [] (str "Hello World"))
(defn -main []
(print (hello)))
I did the evolution of declarations to explain better
So, you can improve the code using the let alternative and the threading macros
Consider use the https://kimh.github.io/clojure-by-example/ and https://tryclojure.org/ to understand these options better :)
I am a newbie to Clojure and I am trying to read a file which should be specified at the command line.
When I try the following, giving the file name at REPL, it is working
(ns testpj.core
(:require [clojure.java.io :as io]))
(defn readfile [filename]
(println (System/getProperty "user.dir"))
(println "Arguments: " filename)
(slurp filename))
And then I run this at REPL and I get the contents of the file
(require '[testpj.core :as h])
(h/readfile file1.txt)
But when I change the above code to main and I try to give the file name at the
command line
lein run file1.txt
(defn -main [& args]
(println (System/getProperty "user.dir"))
(println "Arguments: " args)
(slurp args))
, I am getting the following error:
"java.lang.IllegalArgumentException: Cannot open <("file1.txt")> as an InputStream."
Can anyone help? Thanks
The argument vector for -main is [& args], which means that -main accepts any number of arguments. Inside the function, the var args will be bound to a list of the arguments passed to it, or nil if no arguments are given to the function. So, to slurp the first argument passed to a function which takes multiple arguments:
(slurp (first args))
there are a few related questions on SO but I just can't seem to figure this out. I've got a very simple test code:
(ns test
(:gen-class)
(:require [clojure.java.io :as io]))
(defn tail-file
[path handler-func]
(org.apache.commons.io.input.Tailer/create
(io/file path)
(proxy [org.apache.commons.io.input.TailerListenerAdapter] []
(handle [this line] (handler-func line)))))
(defn -main
[& args]
(tail-file "c:/tmp/test.txt" println)
(read-line))
This results in:
Exception in thread "Thread-0" clojure.lang.ArityException: Wrong number of args (2) passed to: core/tail-file/fn--28
That's strange because tail-file takes two arguments ([path handler-func]).
You should omit this in handle definition, since it is declared implicitly as stated in the docs
Each method fn takes an additional implicit first arg, which is bound
to 'this.
this should be explicitly set when using reify
Notice that the error message didnt say there was an error in tail-file, but in some function generated in tail-file: core/tail-file/fn--28, namely, fn--28.
How do I call a function in one Clojure namespace, bene-csv.core from another namespace, bene-cmp.core? I've tried various flavors of :require and :use with no success.
Here is the function in bene-csv:
(defn ret-csv-data
"Returns a lazy sequence generated by parse-csv.
Uses open-csv-file which will return a nil, if
there is an exception in opening fnam.
parse-csv called on non-nil file, and that
data is returned."
[fnam]
(let [ csv-file (open-csv-file fnam)
csv-data (if-not (nil? csv-file)
(parse-csv csv-file)
nil)]
csv-data))
Here is the header of bene-cmp.core:
(ns bene-cmp.core
.
.
.
(:gen-class)
(:use [clojure.tools.cli])
(:require [clojure.string :as cstr])
(:use bene-csv.core)
(:use clojure-csv.core)
.
.
.
The calling function -- currently a stub -- in (bene-cmp.core)
defn fetch-csv-data
"This function merely loads the two csv file arguments."
[benetrak-csv-file gic-billing-file]
(let [benetrak-csv-data ret-csv-data]))
If I modify the header of bene-cmp.clj
(:require [bene-csv.core :as bcsv])
and change the call to ret-csv-data
(defn fetch-csv-data
"This function merely loads the two csv file arguments."
[benetrak-csv-file gic-billing-file]
(let [benetrak-csv-data bcsv/ret-csv-data]))
I get this error
Caused by: java.lang.RuntimeException: No such var: bcsv/ret-csv-data
So, how do I call fetch-csv-data?
Thank You.
You need to invoke the function, not just reference the var.
If you have this in your ns:
(:require [bene-csv.core :as bcsv])
Then you need to put parentheses around the namespace/alias qualified var to invoke it:
(let [benetrak-csv-data (bcsv/ret-csv-data arg)]
; stuff
)
I have defined a -main function in a :gen-class :main true namespace in Clojure. I am trying to test it from the REPL.
My main function looks like this:
(defn -main [& args]
; ...
)
and I am trying to call it with (ns/-main "-x" "foo"), (ns/-main "-x foo"), (ns/-main ["-x" "foo"]), (ns/-main (into-array String ["-x" "foo"]), etc., and all give me various errors.
How do I call this function from the REPL and pass in some command line arguments to test it?
Thanks.
I tried to reproduce it:
(defn -main [& args]
(apply str args)
)
Then called like:
(-main "a" "b" "c")
And it evaluated to:
"abc"
As it should..
Be sure to check are you using the right namespace identifier, also see if anything weird is happening inside your -main function, like using a string as a number..
Also, it wouldn't hurt to see your error message on this..