Clojure REPL not printing prior to asking for input - clojure

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.

Related

How to make Clojure command line

I am new to Clojure, I wish to create a command line in clojure.
I am using lein, The app is simply waiting for user to type something and when press enter, it will print the line.
I cannot seems to make Clojure wait forever with lein run
Is there any other way?
Here is my code.
(defn -main [& args]
(read-line)
)
so when I type something and press enter, the whole code stops,
I want to take the input of user typing and process it continuously.
I mean each time user press enter, he/she should be able to continue to next line and program will run forever.
You need to loop for the user inputs then and provide some means to break the loop (yet, ctrl-c also works). E.g.
(loop []
(let [input (read-line)]
(if (= input "quit")
(println "bye")
(do
(println "You said: " input)
(recur)))))

How is Clojure's read-line used properly in a do statement?

I'm puzzled by the following behavior:
(do (println "Say hi.") (println (read-line)))
I would expect the message "Say hi." to appear in the console before the program blocks and waits for input. Instead the program blocks right away and only outputs "Say hi." after the user has responded. What's going on here and how is this program written properly?
If you look at the source of println you'll see it calls prn. When you look at the source of prn you'll see it flushes *out* on a newline when *flush-on-newline* is bound to true.
What is the value of *flush-on-newline* in your REPL?
This is probably a buffering issue. Try issuing a (flush) before the readline call.

Clojure: *out* vs System/out

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.

Getting a dump of all the user-created functions defined in a repl session in clojure

Is there a way to get a dump of all the source code I have entered into a repl session. I have created a bunch of functions using (defn ...) but did it 'on the fly' without entering them in a text file (IDE) first.
Is there a convenience way to get the source back out of the repl session?
I note that:
(dir user)
will give me a printed list of type:
user.proxy$java.lang.Object
so I can't appear to get that printed list into a Seq for mapping a function like 'source' over. And even if I could then:
(source my-defined-fn)
returns "source not found"...even though I personally entered it in to the repl session.
Any way of doing this? Thanks.
Sorry, but I suspect the answer is no :-/
The best you get is scrolling up in the repl buffer to where you defined it. The source function works by looking in the var's metadata for the file and line number where the functions code is (or was last time it was evaluated), opening the file, and printing the lines. It looks like this:
...
(when-let [filepath (:file (meta v))]
(when-let [strm (.getResourceAsStream (RT/baseLoader) filepath)]
(with-open [rdr (LineNumberReader. (InputStreamReader. strm))]
(dotimes [_ (dec (:line (meta v)))] (.readLine rdr))
...
Not including the full source in the metadata was done on purpose to save memory in the normal case, though it does make it less convenient here.

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