Clojure-是否可以在doseq语句中增加变量?
我试图迭代给定目录中的文件列表,并在其名称中添加递增变量I={1,2,3..} 下面是我用来迭代文件并更改每个文件名的代码:Clojure-是否可以在doseq语句中增加变量?,clojure,Clojure,我试图迭代给定目录中的文件列表,并在其名称中添加递增变量I={1,2,3..} 下面是我用来迭代文件并更改每个文件名的代码: (defn addCounterToExtIn [d] (def i 0) (doseq [f (.listFiles (file d)) ] ; make a sequence of all files in d (if (and (not (.isDirectory f)) ; if file is not a directry and
(defn addCounterToExtIn [d]
(def i 0)
(doseq [f (.listFiles (file d)) ] ; make a sequence of all files in d
(if (and (not (.isDirectory f)) ; if file is not a directry and
(= '(\. \i \n) (take-last 3 (.getName f))) ) ; if it ends with .in
(fs/rename f (str d '/ i (.getName f)))))) ; add i to start of its name
当
doseq
迭代每个文件时,我不知道如何增加I
。或者,是否有更好的循环来实现期望的结果?这是我头脑中的第一个方法。这并不理想,但肯定比问题所提出的更为地道
(def rename-one-file! [file counter]
(if (and (not (.isDirectory file))
(= ".in" (str (take-last 3 (.getName file)))))
(fs/rename file (file (parent dir)
(str counter (.getName file)))))
(defn iterate-files-with-counter [fn dir]
(loop [counter 0
remaining-files (.listFiles (file dir))]
(let [current-file (first remaining-files)]
(fn file counter)
(recur (+ counter 1) (rest remaining-files))))
(def add-counter-to-ext-in-dir
(partial iterate-files-with-counter rename-one-file!))
请注意,实际执行重命名的工作与迭代文件的工作是分开的。一般来说,拥有大量的小功能比拥有少量的大功能要好,并且使这些功能可重用/独立,除非您选择将它们一起使用,否则比这更好。使用和:
将映射索引中的函数更改为重命名即可。
pdf文件的示例输出:
([0 #<File /home/eduard/Downloads/some.pdf>] ...)
([0#]…)
为什么要将变量的范围扩展到它所用于的操作之外?def
创建一个顶级var
,正如Charles Duffy指出的那样,它是一个顶级值,存在于函数运行之外,更重要的是,如果要进行变异,通常是错误的。此外,clojure中的惯用用法是完全消除突变的直接使用(如下面他的回答所示)。感谢您的解释您可能会发现这段代码很有用:注意,这都是即兴编写的,没有经过测试,所以它肯定不是完美的——但目标是展示惯用语/良好实践。在这种情况下,遵循惯用语是否真的很重要,或者我也可以使用变异,但你只是想向我展示同样的惯用方法?@YechielLabunskiy,使用vars进行变异会导致现实世界中的错误和性能问题。正确使用习惯用法并不总是很重要,但最初的代码有实际的错误(例如,想想如果同时从两个线程调用它会发生什么)。谢谢——当您发现这个问题时,我实际上正在寻找地图索引来修改我自己的答案。:)请注意,file seq是递归的,也将返回子目录中的文件。是否有方法使索引以0以外的值开始?@YechielLabunskiy您可以(inc i)
在映射索引的函数内。我想你已经得到了这个答案:)
([0 #<File /home/eduard/Downloads/some.pdf>] ...)