Clojure:*out*vs System/out

RGr*_*run 7 clojure

我正在尝试将我用Java编写的一个小型控制台程序翻译成Clojure,但是我在弄清楚Clojure的标准*out*var和对象之间的区别时遇到了一些麻烦System/out.我的印象是他们是同一个东西,但在我的测试中,他们似乎是不同的.

在我的程序中,我提示用户输入一个数字,我希望提示和输入文本在同一行.在Java中,我打印了提示,System.out.print()然后扫描仪读取输入.

以下是我在Clojure中首次尝试类似的事情.虽然print函数看起来应该在它之前触发read-line,但它会立即阻塞输入并在混乱之后打印所有内容:

(defn inp1 []
    (print "Enter your input: ")
    (let [in (read-line)]
        (println "Your input is: " in)))
Run Code Online (Sandbox Code Playgroud)

以下是我的下一次尝试,使用*out*.它遇到与上述功能相同的问题:

(defn inp2 []
    (.print *out* "Enter input: ")
    (let [i (read-line)]
        (println "You entered: " i)))
Run Code Online (Sandbox Code Playgroud)

在我的第三次尝试中,我终于通过System/out直接使用来实现它:

(defn inp3 []
    (let [o System/out]
        (.print o "Enter input: ")
        (let [i (read-line)]
            (println "You entered: " i))))
Run Code Online (Sandbox Code Playgroud)

我很高兴我终于得到了它的工作,但我很困惑,为什么第三个工作方式是我想要的方式,而前两个没有.为什么前两个会立即阻止?任何人都可以对此有所了解吗?

Cha*_*ffy 8

根据文档:

*out* - 表示打印操作的标准输出的java.io.Writer对象.默认为System/out,包含在OutputStreamWriter中

...所以,你有一层包装.查看该层的文档(强调添加):

每次调用write()方法都会导致在给定字符上调用编码转换器.生成的字节在写入底层输出流之前累积在缓冲区中.可以指定此缓冲区的大小,但默认情况下,它足够大,可用于大多数用途.请注意,传递给write()方法的字符不会被缓冲.

...重点补充.从OutputStreamWriter缓冲区开始,您需要调用.flush以强制写入内容.