Clojure 如何获取调用Java方法的Fn?

Clojure 如何获取调用Java方法的Fn?,clojure,Clojure,我在学Clojure。我写这段代码是为了递归地遍历目录 (tree-seq #(.isDirectory %1) #(.listFiles %1) (File. "/my-directory")) 为什么我不能将.isDirectory用作Clojure中的一级函数?是否有更好的方法重写此代码?您可以查看(使用树序列)以了解其工作原理 顺便说一下:你的代码对我来说非常好。我只需要使用java.io.File而不是REPL中的File,这样它就知道java类了。java方法不是clojure函数

我在学Clojure。我写这段代码是为了递归地遍历目录

(tree-seq #(.isDirectory %1) #(.listFiles %1) (File. "/my-directory"))

为什么我不能将
.isDirectory
用作Clojure中的一级函数?是否有更好的方法重写此代码?

您可以查看(使用树序列)以了解其工作原理


顺便说一下:你的代码对我来说非常好。我只需要使用java.io.File而不是REPL中的File,这样它就知道java类了。

java方法不是clojure函数,因为你不能单独调用一个方法;您必须对一个对象调用一个方法,并且它必须是该方法所期望的类型的对象。换句话说,在java中,方法不能与其定义类完全分离(至少不能有效地分离)


#(.foo%)的另一个替代品是(memfn-foo),自从引入了#(…)之后,几乎没有人再使用它了。

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惯用代码,我还将使用

      #(.foo %)
      
      正如Joost Diepenmaat所做的那样(但我相信它可能被忽略了)

      我还建议你读书