9

最近我寫了一個小小的CLI腳本,它需要反覆從控制檯讀取日期(要讀取的日期的數量已計算出來,並且每次都可能會有所不同)。示例Ruby代碼給你的想法:用於編寫Clojure代碼以反覆從控制檯讀取行的語言方式?

dates = x.times.collect { print "Enter date: "; Date.parse(gets.chomp) } 

只爲它赫克,我寫劇本用Clojure,彼時使用一些比較難看的代碼swap!loop...recur。我想知道在Clojure中達到預期效果的最簡潔的方法是什麼。 (Clojure中確實有dotimes,但它不保留值從評估身體......因爲可能從強調純函數式編程語言可以預期返回。)

回答

7

如果你的目標是結束了由用戶隨後進入正好x日期序列:

(for [line (repeatedly x read-line)] (DateFormat/parse line)) 

,或者使用map

(map DateFormat/parse (repeatedly x read-line)) 

當心Clojure的懶惰序列:用戶將被要求在需要的時候進入更多的日期。如果你的目標是讓用戶一次輸入所有時間(在啓動時說),然後使用doall

(map DateFormat/parse (doall (repeatedly x read-line))) 

這將一次讀取所有日期,但會解析它們懶洋洋地還在,所以日期格式驗證可能在程序中失敗很多。您可以將doall一個級別解析及時,以及:

(doall (map DateFormat/parse (repeatedly x read-line))) 

你也可以使用一個輔助函數來閱讀提示行:

(defn read-line-with-prompt [prompt] 
    (print prompt) 
    (read-line)) 

然後將其替換read-line之一:

#(read-line-with-prompt "Enter date: ") 

(partial read-line-with-prompt "Enter date: ") 
+0

很好的答案......謝謝你提供這麼多選擇。我想我會定義一個'read-date'輔助函數,並簡單地使用'(反覆x讀取日期)'。我認爲隨後的處理將在我對控制檯做任何其他事情之前進行強制評估,所以'doall'可能*是不必要的,但是在我的工具包中這樣做很好,我相信我會找到使用的機會它後來。 – 2012-07-15 10:15:30

4

你可以做這樣的事情:

(defn read-dates [n] 
    (doall (for [_ (range n)] (java.util.Date/parse (read-line))))) 

(def my-dates (read-dates 5)) ;Read 5 dates from console 
10

當到達文件結束時,讀取行返回nil。在按CTRL-d (Windows上的CTRL-z)的控制檯上。

您可以使用此代碼來利用這一點:

(doseq [line (repeatedly read-line) :while line] 
    (do-something-with line)) 

如果你一定要讀線的固定號碼,您可以使用:

(repeatedly n read-line) 
+1

'doseq'中':while'的使用非常有趣,我從未見過它。涼! – dimagog 2012-07-14 22:38:02