Reputation: 866
I am currently trying to learn Clojure and as part of my practical training, I am
implementing the very basic behavior of some of the well known Unix tools like grep
,
cat
, ls
and so on.
While implementing cat
, I stumbled upon some seemingly strange behavior of
slurp
. When I run the following code with lein run some-file.txt
while some-file.txt
lies within the current directory, the content is printed to STDOUT as expected.
(ns cat.core
(:gen-class))
(defn -main
"Reads the content of its arguments representing filenames and outputs the
content in succession."
[& filenames]
(doseq [filename filenames]
(println "Reading" filename) ; Just for debugging purposes
(print (slurp filename))))
However, if I uberjar
the project with
lein compile
lein uberjar
and then cd
to target/uberjar
to run the standalone JAR with
java -jar cat-0.1.0-SNAPSHOT-standalone.jar some-file.txt
(with the text file present in that directory),
nothing but my debug message gets printed. What I find so strange is that there is no error
message being shown, so it seems to me that the file can be found. If I run the
JAR with a file that does not exist as parameter, I get an exeption that the specified
file cannot be found (as expected).
Because I am working on a Windows machine, a colleague suggested that perhaps Windows shadow files might be a problem. So I tested the program under Linux again and the same behavior occured. So this seems to be a "problem" with my Clojure understanding / my project settings.
My question is: Why is slurp
's (or the program's) behavior different when running
with lein run
and when running the standalone JAR with java -jar cat-0.1.0-SNAPSHOT-standalone.jar
and what can I do to solve this?
As the file parameter is not a resource that is compiled into the JAR, there is no
need for (slurp (clojure.java.io/resource filename))
if I am not mistaken.
Upvotes: 1
Views: 330
Reputation: 596
print
does not flush the output buffer. You need to use flush
after your print
statement, or use another println
, which flushes on newline:
(defn -main
"Reads the content of its arguments representing filenames and outputs the
content in succession."
[& filenames]
(doseq [filename filenames]
(print (slurp filename))
(flush)))
Upvotes: 4