2016-04-15 59 views
7

我想翻译一个小控制台程序,我用Java写成Clojure的,但我有一个小麻烦搞清楚Clojure的标准*out* VAR和对象之间的差异System/out。我的印象是他们是同一件事,但在我的测试中,他们似乎有所不同。Clojure的:*总分* VS系统的输入/输出

在我的节目我提示用户输入一个数字,我想提示和输入文本是在同一行。在Java中,我用System.out.print()打印提示,然后扫描仪读取输入。

下面是我在Clojure中类似的第一次尝试。尽管print功能似乎应该火read-line之前,它会立即对输入块和一个混乱的烂摊子后,打印出的一切:

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

下面是我的第二次尝试,使用*out*。它从同一个问题,因为上面的功能受到影响:

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

在我的第三次尝试,我终于得到它通过直接使用System/out工作:

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

我很高兴我终于它得到工作,但我为什么第三个以我想要的方式工作时,前两个不这样做,我感到非常困惑。为什么前两个块立即堵塞?任何人都可以对此有所了解吗?

回答

8

the docs

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

...所以,你有一层包装。查看文档for that layer(强调增加):

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

...加着重号。由于OutputStreamWriter缓冲区,你需要调用.flush强制内容写入。

+0

我现在,它的缓冲看,我需要首先调用.flush就可以了。我没有意识到一个是一个流,另一个是一个作家。谢谢! – RGrun