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: Unable to resolve symbol: foo in this context, compiling...:

しかし、シンボルを引用しようとすると

(f 'foo)

別のエラーが発生しますが、予想されるエラーも発生します。

IllegalArgumentException 一致するフィールドが見つかりません: クラス com.dullesopen.srl.FunCall のメソッド clojure.lang.Reflector.getInstanceField (Reflector.java:271)

特殊な形式のドキュメントによると、エラーが予想されます。(ドット) 2 番目の引数は、フィールドまたはメソッドの名前のいずれかに一致すると見なされるため、Clojure の観点からは実際のシンボルではありません。

以下のアプローチは問題を解決しますが、私は余分なものが好きではありませんmemfn。私にとっては、Java メソッドが実際には Clojure のファースト クラス オブジェクトではないことを示しています。

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

(f (memfn foo))

.問題は、メソッド名を取得するために 2 番目の引数を何らかの方法で解決/評価する必要があることを特別な形式に「示す」方法はありますか? それとも、ドットに似ているが、2 番目の引数が解決された別の特別なものがあるのでしょうか?

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 に答える