最近我在写这需要一点CLI脚本来多次从控制台读取日期(日期读取计算的数量和每个时间可能会有所不同)。 样品Ruby代码给你的想法:
dates = x.times.collect { print "Enter date: "; Date.parse(gets.chomp) }
只是它的心里很不舒服,我用Clojure写的剧本,彼时使用一些比较难看的代码swap!
和loop...recur
。 我想知道什么最干净的方式来实现Clojure中所期望的效果会。 (Clojure中确实有dotimes
,但它不会保留评估身体......因为可能从强调纯函数式编程语言可以预期的返回值。)
如果你的目标是完全相同的序列落得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: ")
读线到达文件结尾时返回零。 在控制台上,当你按CTRL-d(在Windows CTRL-Z)即到。
您可以使用此代码来利用这一点:
(doseq [line (repeatedly read-line) :while line]
(do-something-with line))
如果你必须阅读线固定数量的,你可以使用:
(repeatedly n read-line)
你可以这样做:
(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
文章来源: Idiomatic way to write Clojure code for repeatedly reading lines from the console?