【发布时间】:2012-11-05 09:39:23
【问题描述】:
我正在学习 Clojure。我写这段代码是为了递归遍历一个目录。
(tree-seq #(.isDirectory %1) #(.listFiles %1) (File. "/my-directory"))
为什么我不能使用.isDirectory 作为 Clojure 中的一流函数?有没有更好的方法来重写这段代码?
【问题讨论】:
标签: clojure
我正在学习 Clojure。我写这段代码是为了递归遍历一个目录。
(tree-seq #(.isDirectory %1) #(.listFiles %1) (File. "/my-directory"))
为什么我不能使用.isDirectory 作为 Clojure 中的一流函数?有没有更好的方法来重写这段代码?
【问题讨论】:
标签: clojure
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"))
这是几行代码,但有以下优点:
【讨论】:
Java 方法不是 clojure 函数,因为您不能单独调用方法;您必须在对象上调用方法,并且它必须是该方法期望的类型的对象。换句话说,在 java 中,一个方法不能与其定义的类完全分离(至少效率不高)。
#(.foo %) 的替代方案是 (memfn foo),在引入 #(...) 之后几乎没有人再使用它了。
【讨论】:
您可以查看sourcecode of file-seq(它使用树序列)来了解它是如何工作的。
顺便说一句:您的代码对我来说非常有效。我只需要在 REPL 中使用 java.io.File 而不是 File,这样它就知道 Java 类。
【讨论】:
你已经得到了正确的答案,但只是为了添加更多的 Clojure 惯用代码,我也会使用
#(.foo %)
正如 Joost Diepenmaat 所做的那样(但我相信它可能被忽视了)。
【讨论】: