Idiomatic way to write Clojure code for repeatedly reading lines from the console?
最近,我正在编写一个小的CLI脚本,该脚本需要从控制台重复读取日期(已读取的日期数是经过计算的,并且每次可能不同)。样本Ruby代码可以帮助您:
1 | dates = x.times.collect { print"Enter date:"; Date.parse(gets.chomp) } |
仅出于此目的,我用Clojure编写了脚本,然后使用
当到达文件末尾时,
read-line返回nil。在控制台上,按CTRL-d(在Windows上为CTRL-z)。
您可以使用以下代码利用此优势:
1 2 | (doseq [line (repeatedly read-line) :while line] (do-something-with line)) |
如果必须阅读固定数量的行,则可以使用:
1 | (repeatedly n read-line) |
如果您的目标是最终输入用户输入的确切
1 | (for [line (repeatedly x read-line)] (DateFormat/parse line)) |
或使用
1 | (map DateFormat/parse (repeatedly x read-line)) |
当心Clojure中的惰性序列:系统将要求用户根据需要输入更多日期。如果您的目标是让用户一次输入所有日期(例如在启动时输入),则使用
1 | (map DateFormat/parse (doall (repeatedly x read-line))) |
这将一次读取所有日期,但仍会延迟解析它们,因此日期格式验证可能会在程序中稍后失败。您也可以将
1 | (doall (map DateFormat/parse (repeatedly x read-line))) |
并且您可以使用助手功能来读取带有提示的行:
1 2 3 | (defn read-line-with-prompt [prompt] (print prompt) (read-line)) |
然后用以下任一替换
1 | #(read-line-with-prompt"Enter date:") |
或
1 | (partial read-line-with-prompt"Enter date:") |
您可以执行以下操作:
1 2 3 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 |