2016-04-15 32 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