Clojure: *out* vs System/out - clojure

I'm trying to translate a small console program I wrote in Java into Clojure, but I'm having a little trouble figuring out the difference between Clojure's standard *out* var and the object at System/out. I was under the impression that they were the same thing, but when during my testing they seem to be different.
In my program I prompt the user to enter a number, and I want the prompt and input text to be on the same line. In Java, I printed the prompt with System.out.print() and then a Scanner read the input.
The following was my first attempt at something similar in Clojure. Though the print function seems like it should fire before the read-line, it immediately blocks on input and prints everything after in a jumbled mess:
(defn inp1 []
(print "Enter your input: ")
(let [in (read-line)]
(println "Your input is: " in)))
The following was my next attempt, using *out*. It suffers from the same problem as the function above:
(defn inp2 []
(.print *out* "Enter input: ")
(let [i (read-line)]
(println "You entered: " i)))
On my third try, I finally got it to work by using System/out directly:
(defn inp3 []
(let [o System/out]
(.print o "Enter input: ")
(let [i (read-line)]
(println "You entered: " i))))
I'm glad I finally got it to work, but I'm deeply confused as to why the third one works the way I want when the first two don't. Why do the first two block immediately? Can anyone shed some light on this?

Per the docs:
*out* - A java.io.Writer object representing standard output for print operations.
Defaults to System/out, wrapped in an OutputStreamWriter
...so, you have a layer of wrapping. Looking at the docs for that layer (emphasis added):
Each invocation of a write() method causes the encoding converter to be invoked on the given character(s). The resulting bytes are accumulated in a buffer before being written to the underlying output stream. The size of this buffer may be specified, but by default it is large enough for most purposes. Note that the characters passed to the write() methods are not buffered.
...emphasis added. Since OutputStreamWriter buffers, you need to call .flush to force content to be written.

Related

Clojure REPL not printing prior to asking for input

I'm writing a generic function that asks for input from the user, validates it via a passed function, and displays a message if the input is bad.
The problem I'm facing is the message asking for input doesn't actually print until after the user has already given the input.
Since I'm using print instead of println, stream buffering is the obvious culprit, but even after flushing after printing, it still doesn't print at the right time. Here's the simplest example of the problem:
(defn- fprint [message]
(print message)
(flush))
(defn simple-interact []
(fprint "123")
(fprint (read-line))
(fprint "456"))
Using IntelliJ IDEA's REPL, running this causes a popup input prompt. If I enter abc into the prompt, it prints 123abc456 at once instead of in parts; 123 isn't printed until after I've already given the input.
I'm using print instead of println because the real function I'm writing displays a given message, and I don't want to force it to print a newline if the intial message is intended to be a prompt. For reference, here's the full function and helpers:
(defn- print-mesage? [message]
(and message (not= message "")))
(defn- fprint [message]
(print message)
(flush))
(defn- fprint? [message]
(if (print-mesage? message)
(fprint message)))
(defn restricted-ask-for-input
"Asks a user for input. Will repeatedly ask until their input is verified via validate-f.
The ask message is displayed once before input is first asked for.
The error message is displayed every time validation fails.
If either of the messages is empty, or falsey, they won't be printed.
The messages dont' have a newline added after them."
[ask-message error-message validate-f]
(fprint? ask-message)
(loop []
(let [in (read-line)]
(if (validate-f in)
in
(do
(fprint? error-message)
(recur))))))
I really need to be able to print prior to asking for input so the user knows what's being asked.
Any help here would be appreciated.
Just as a test after posting this I tried changing fprint to use println instead, and the behavior is the same.

Clojure print function

Complete Clojure newbie here so I'm probably missing something fundamental about the way clojure works but I'm not understanding the way Clojure evaluates functions.
(defn get-output []
(print "Enter: Width <RTN> Height <RTN> Price <RTN> Shape <RTN>")
(print (calculate (read-string (read-line))))
I'm used to a language like Ruby or C where the first print function would be evaluated, printing the string to the terminal. Then the second print function would be evaluated, prompting the user for input.
However, what actually happens is that the terminal first prompts the user for input and prints "Enter: Width Height Price Shape " after. Finally the program outputs the return value from calculate.
Why are these print statements not executing as I expect?
The statements are executing in the order that you expect. The issue is that print doesn't flush the out buffer. You can either call (flush) after the first print statement or perhaps you want to call println

How to read all lines from stdin in Clojure

I'm writing a Brainf*** interpreter in Clojure. I want to pass a program in using stdin. However, I still need to read from stdin later for user input.
Currently, I'm doing this:
$ cat sample_programs/hello_world.bf | lein trampoline run
My Clojure code is only reading the first line though, using read-line:
(defn -main
"Read a BF program from stdin and evaluate it."
[]
;; FIXME: only reads the first line from stdin
(eval-program (read-line)))
How can I read all the lines in the file I've piped in? *in* seems to be an instance of java.io.Reader, but that only provides .read (one char), .readLine (one line) and read(char[] cbuf, int off, int len) (seems very low level).
It's simple enough to read all input data as a single string:
(defn -main []
(let [in (slurp *in*)]
(println in)))
This works fine if your file can fit in available memory; for reading large files lazily, see this answer.
you could get a lazy seq of lines from *in* like this:
(take-while identity (repeatedly #(.readLine *in*)))
or this:
(line-seq (java.io.BufferedReader. *in*))
which are functionally identical.

What happens to second println statement? (Clojure repl)

When I call this small function in the clojure REPL it only prints the first hello world, not hello mars. Why is that? It's not lazy (as far as I understand) otherwise the exception wouldn't get hit, in addition SO tells me println causes a flush.
(defn foo
"I don't do a whole lot."
[x]
(println x "Hello, World!")
(map (fn [x] (let [_ (println "Hello, Mars")
__ (throw (Exception. "talking to many planets"))]
{ :aliens? false }
)) [1 2 3])
)
Output:
(foo nil) nil Hello, World!
Exception talking to many planets test.repl/foo/fn--6580
(form-init13300486174634970.clj:5)
First of all, map is actually lazy, so foo returns a LazySeq, which is then forced when the REPL prints it. Now when I run your example using bare Clojure (java -jar clojure.jar), I get the following output:
user=> (foo nil)
nil Hello, World!
(Hello, Mars
Exception talking to many planets user/foo/fn--1 (NO_SOURCE_FILE:5)
user=>
I get the same result with both Clojure 1.4.0 and 1.5.1.
Now if I run via lein repl, I get the output you describe. So it appears that something in the nrepl chain is affecting how things are printed. This makes sense since nrepl is designed to communicate with clients over the network. There appears to be a slight bug, however, in its handling of this case. Or perhaps it re-binds flush-on-newline to false when printing the value? Sorry, I haven't dived into the code deep enough to give a more definite answer.
Incidentally, if you wrap the function call in a println, i.e. (println (foo nil)), then you get the expected output shown above.
Okay I have an idea. Map returns a lazy seq. The repl calls println (or similar) on the map which attempts to realize it, calling .toString() (or similar). Internally when print/ln is called within a print/ln it saves the output until its finishes it own, thus an exception will mean the other bits collected (print within a print) call aren't flushed.

How can I capture the standard output of clojure?

I have some printlns I need to capture from a Clojure program and I was wondering how I could capture the output?
I have tried:
(binding [a *out*]
(println "h")
a
)
: but this doesn't work
(with-out-str (println "this should return as a string"))
Just to expand a little on Michiel's answer, when you want to capture output to a file you can combine with-out-str with spit.
When you don't want to build up a huge string in memory before writing it out then you can use with-out-writer from the clojure.contrib.io library.
with-out-writer is a macro that nicely encapsulates the correct opening and closing of the file resource and the binding of a writer on that file to *out* while executing the code in its body.
Michiel's exactly right. Since I can't add code in a comment on his answer, here's what with-out-str does under the covers, so you can compare it with your attempt:
user=> (macroexpand-1 '(with-out-str (println "output")))
(clojure.core/let [s__4091__auto__ (new java.io.StringWriter)]
(clojure.core/binding [clojure.core/*out* s__4091__auto__]
(println "output")
(clojure.core/str s__4091__auto__)))
Your code was binding the existing standard output stream to a variable, printing to that stream, and then asking the stream for its value via the variable; however, the value of the stream was of course not the bytes that had been printed to it. So with-out-str binds a newly created StringWriter to *out* temporarily, and finally queries the string value of that temporary writer.