我正在学习Clojure。我编写了这段代码来递归遍历一个目录。
(tree-seq #(.isDirectory %1) #(.listFiles %1) (File. "/my-directory"))
为什么我不能将.isDirectory
用作Clojure中的第一类函数?有没有更好的方法来重写这段代码?
答案 0 :(得分:7)
Joost认为Java方法不是一流的功能。
作为处理这个问题的方法,我通常喜欢将Java函数包装在Clojure函数中(或者找到一个已经执行此操作的库),然后很容易以惯用的一流方式使用它们:
(defn directory? [^java.io.File file]
(.isDirectory file))
(defn list-files [^java.io.File file]
(.listFiles %1))
(tree-seq directory? list-files (File. "/my-directory"))
这是一些代码行,但具有以下优点:
答案 1 :(得分:6)
Java方法不是clojure函数,因为你不能自己调用方法;你必须在一个对象上调用一个方法,它必须是该方法所期望的类型的对象。换句话说,在java中,方法不能与其定义类完全分离(至少不能有效)。
#(。foo%)的另一种选择是(memfn foo),在#(...)被引入之后几乎没有人再使用它了。
答案 2 :(得分:1)
您可以查看sourcecode of file-seq(使用树序列)查看其工作原理。
顺便说一下:你的代码对我来说非常好。我只需要在REPL中使用java.io.File而不是File,因此它知道Java类。
答案 3 :(得分:1)
您已经获得了正确的答案,但只是添加了更多Clojure惯用代码,我还会使用
#(.foo %)
正如Joost Diepenmaat所做的那样(但我相信它可能会被忽视)。