Command line 编写Clojure代码以从控制台重复读取行的惯用方法?

Command line 编写Clojure代码以从控制台重复读取行的惯用方法?,command-line,clojure,functional-programming,console-input,Command Line,Clojure,Functional Programming,Console Input,最近,我正在编写一个小的CLI脚本,它需要从控制台重复读取日期(要读取的日期数是经过计算的,每次都可能不同)。示例Ruby代码让您了解: dates=x.times.collect{print“输入日期:;date.parse(get.chomp)} 只是为了见鬼,我用Clojure编写了脚本,最后使用了一些相当难看的代码swap和循环…重复出现。我想知道在Clojure中实现预期效果的最干净的方法是什么。(Clojure确实有dotimes,但它不保留从评估主体返回的值……这可能是强调纯函数

最近,我正在编写一个小的CLI脚本,它需要从控制台重复读取日期(要读取的日期数是经过计算的,每次都可能不同)。示例Ruby代码让您了解:

dates=x.times.collect{print“输入日期:;date.parse(get.chomp)}

只是为了见鬼,我用Clojure编写了脚本,最后使用了一些相当难看的代码
swap
循环…重复出现
。我想知道在Clojure中实现预期效果的最干净的方法是什么。(Clojure确实有
dotimes
,但它不保留从评估主体返回的值……这可能是强调纯函数式编程的语言所期望的。)

您可以这样做:

(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

到达文件末尾时,读取行返回nil。在控制台上,当您按CTRL-d(Windows上按CTRL-z)时

您可以使用此代码来利用这一点:

(doseq [line (repeatedly read-line) :while line]
    (do-something-with line))
如果必须阅读固定数量的行,则可以使用:

(repeatedly n read-line)

如果您的目标是最终由用户输入一系列精确的
x
日期,则:

(for [line (repeatedly x read-line)] (DateFormat/parse line))
或使用
映射

(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-with-prompt "Enter date: ")


非常有趣的
用法:虽然在
doseq
中使用了
,但我以前从未见过它。酷!很好的回答。。。谢谢你提供这么多的选择。我想我将定义一个
读取日期
帮助函数,并简单地使用
(重复x读取日期)
。我认为后续处理将在我使用控制台执行任何其他操作之前强制执行评估,因此,
doall
可能是不必要的,但是在我的工具箱中有它是很好的,我相信我以后会找到机会使用它。
(partial read-line-with-prompt "Enter date: ")