我想做一个clojure函数,返回一个目录中今天被改变的文件.它是功能的一部分=>给我所有今天被改变的文件,在文件中循环并寻找一个特定的值。同时列出文件和带有该值的行。
我得到了解析部分+列出行文件的工作,以及 "改变的文件",然而我很难将两者合并。
到目前为止,我设计的查找更改文件的函数是。
(defn returnfilelist
"returns all the files changed today in a directory"
[d]
(def dir (io/file d))
(def files (for [file (file-seq dir) :when (= (datetostr (Date.(.lastModified file))) (datetostr (new Date))) ](str file )))
(doseq [f files] (println f) )) ;; <==== this indeed shows the files changed today...
我创建了datetostr函数来进行实际的日期比较。
(defn datetostr [date]
(str (.format (java.text.SimpleDateFormat. "yyyyMMdd")(.getTime date))))
这个函数确实列出了所有今天修改过的文件 我现在想做的是把 "文件 "传入一个函数,比如:
(defn readdir [d]
(ff/returnfilelist d)) ;; more to add...
这样的函数中进行进一步的处理。
我希望能得到一些帮助,我可能监督的东西很简单,却让我烦了几个小时了。我一直在clojure文档和互联网上搜索,然而我没有找出正确的搜索表达式来得到答案。
方向已经足够了,我喜欢学习,而且我对clojure的编程相当陌生。
有几件事。
def
内的函数。 def
定义并绑定软件包全局命名空间中的符号,这几乎不是你想要做的。在包的全局命名空间中定义和绑定符号,这几乎不是你想要做的。let
而不是函数本地符号绑定。下面是经过适当修改的 returnfilelist (我尽可能地保持它与您的原始实现接近,以说明让您的代码工作的关键变化:其他答案使用了 filter
更为习惯,应该是首选)。)
(defn returnfilelist
"returns all the files changed today in a directory"
[d]
(let [dir (io/file d)
files (for [file (file-seq dir)
:when (= (datetostr (Date.(.lastModified file)))
(datetostr (new Date)))]
(str file))]
(doseq [f files] (println f)) ;; leaving this in for debugging
files)) ;; <--- the actual return value
...然后readdir就变成了:
(defn readdir [d]
(let [todays-files (ff/returnfilelist d)]
;; more to add...
))
要想从函数中返回一个值 必须由函数中执行的最后一条语句产生。在你的例子中,你并没有返回任何东西,而是在全局范围内定义了新的值(这本身就是不好的做法);你应该使用 let
为本地值。
(defn files-modified-today
[path]
(let [dir (io/file dir)]
(filter modified-today? (file-seq dir))))
(执行 modified-today?
根据您的喜好,例如,像您在问题中那样,使用 datetostr
.)
由于 for
形式是函数中执行的最后一条语句,它的结果将作为函数的返回值,并可以从其他地方使用。
(defn read-dir
[path]
(for [f (files-modified-today path)]
(let [result (parse-file f)]
[f result]))))
这将返回一个对的序列,包含匹配的文件作为第一个元素,以及函数的结果 parse-file
不管是什么)作为第二种。
希望我没有完全错过你的问题。
你的问题有点模糊。 另外,你写的代码似乎远没有达到习以为常的程度。 我重写了你下面的一些函数,向你介绍一些常见的clojure习语。
(import 'java.util.Date)
(defn date->str [date]
(-> (java.text.SimpleDateFormat. "yyyyMMdd") ;thread-first macro
(.format (.getTime date))
str))
(defn todays-files [dir]
"returns all the files changed today in a directory"
(let [today (new Date)] ;let bindings
(->> (file-seq (clojure.java.io/file dir)) ;thread-last macro.
(filter #(= (date->str (Date. (.lastModified %))) (date->str today)))
(map str))))
线程宏(thread-first和thread-last)用于创建管道,在管道中进行一次数据转换,然后传递到下一步。
在函数中应该使用let绑定而不是defs。
函数名应该用破折号来代替通常的空格。 在转换函数中使用->也是很常见的。 例如,date-to-str变成了date->str。
一个宏来处理目录中的文件列表--递归地或只在父目录中。它还可以搜索具有特定扩展名的文件。
;; lists all the files recursively inside the directory passed as d like "."
(defmacro my-rec-list
"generate the recursive list" {:added "1.0"}
[d str rec]
`(->> ~d
clojure.java.io/file
~(if (= rec "rec")
`file-seq
`(.listFiles))
~(cond
(= str "file") `(filter #(.isFile %))
(= str "dir") `(filter #(.isDirectory %))
:always `(filter #(.matches (.getPathMatcher
(java.nio.file.FileSystems/getDefault)
~str) (.getFileName (.toPath %)))))
(mapv #(.getAbsolutePath %))))
(defn my-rec-ls-file
"generate the recursive list for only files in a directory"
[d ]
(my-rec-list d "file" "rec"))
(defn my-rec-ls-dir
"generate the recursive list for only directory"
[d ]
(my-rec-list d "dir" "rec"))
(defn my-rec-ls-jpg
"generate the recursive list for files and directory"
[d ]
(my-rec-list d "glob:*.jpg" "rec"))
(defn my-ls-file
"generate the recursive list for only files in a directory"
[d ]
(my-rec-list d "file" "norec"))
(defn my-ls-dir
"generate the recursive list for only directory"
[d ]
(my-rec-list d "dir" "norec"))
(defn my-ls-jpg
"generate the recursive list for files and directory"
[d ]
(my-rec-list d "glob:*.jpg" "norec"))
它导致了不同的功能,可以调用directory来获得文件列表,目录或匹配的扩展文件-递归或非递归。例子是---------------------------。
(def directory (clojure.java.io/file "/Path/to/Directory"))
(my-rec-ls-jpg directory) ;; find all jpg file recessively in directory
(my-ls-jpg directory) ;; find jpg file in current directory