如何获得一个调用Java方法的Fn?

woo*_*ngs 3 clojure

我正在学习Clojure.我写了这段代码来递归遍历一个目录.

(tree-seq #(.isDirectory %1) #(.listFiles %1) (File. "/my-directory"))
Run Code Online (Sandbox Code Playgroud)

为什么我不能.isDirectory在Clojure中用作一流函数?有没有更好的方法来重写此代码?

mik*_*era 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"))
Run Code Online (Sandbox Code Playgroud)

这是一些代码行,但具有以下优点:

  • 您可以在函数中添加类型提示以避免反射(如上所述)
  • 最终的代码更清晰,更具惯用性
  • 您已经从底层Java互操作中抽象出来了


Joo*_*aat 6

Java方法不是clojure函数,因为你不能自己调用​​一个方法; 你必须在一个对象上调用一个方法,它必须是该方法所期望的类型的对象.换句话说,在java中,方法不能与其定义类完全分离(至少不能有效).

#(.foo%)的另一种选择是(memfn foo),在引入#(...)之后几乎没有人再使用它了.