3

假设我们有一个 Java 类:

public class Fun {
   public int foo () {
    return 1;
   }

   public  int bar () {
      return 2;
   }

}

下面的代码在 Clojure 中不起作用:

(defn f [method]
(. (new Fun) method)) 

(f foo)

产生预期的错误(这里没有问题):

CompilerException java.lang.RuntimeException:无法解析符号:在此上下文中的 foo,正在编译...:

但是如果我尝试引用符号

(f 'foo)

它会产生一个不同但也是预期的错误:

IllegalArgumentException 找不到匹配的字段:com.dullesopen.srl.FunCall clojure.lang.Reflector.getInstanceField 类的方法(Reflector.java:271)

该错误是预期的,因为根据特殊形式的文档。(点)第二个参数被假定为匹配字段或方法的名称,因此从 Clojure 的角度来看,它不是一个实际的符号。

下面的方法解决了这个问题,但我不喜欢额外的memfn. 对我来说,这表明 Java 方法实际上并不是 Clojure 中的第一类对象。

(defn f [method]
   (method (new FunCall))) 

(f (memfn foo))

所以问题是:有没有办法“指示”.第二个参数应该以某种方式解析/评估以获得方法名称的特殊形式?或者也许还有另一个类似于 dot 但解决了第二个参数的特殊情况?

4

1 回答 1

3

您的理解是正确的,Java 方法实际上不是 clojure 中的一等公民。您不能独立于其类传递方法。我能想到的最接近的是传递知道类和方法的函数,或者使用宏来为每个类构建对方法的调用。如果您不喜欢上面的方法(对我来说看起来非常好),那么可以直接使用宏来完成,尽管我个人更喜欢您的方法:

user> (defmacro f [method]
        `(. (String. "asdf") ~method))
#'user/f
user> (f hashCode)
3003444

PS:memfn被函数文字语法所取代。它很少使用。

于 2015-02-20T21:37:11.060 回答