8

Character/isWhitespace の正しい使用法は次のとおりです。

(Character/isWhitespace \a) => false
(Character/isWhitespace \ ) => true

ただし、私の最初の試みはこれであり、エラーがわかりにくいと思います。

(Character/isWhitespace "")
  =>  IllegalArgumentException No matching method found: isWhitespace
  => clojure.lang.Reflector.invokeMatchingMethod (Reflector.java:80)

そのIllegalArgument部分は理にかなっていますが、「一致する方法が見つかりません」と表示されるのはなぜですか? 明らかに関数は存在します。

明確化

私がこの質問をしている理由は、私が Clojure に不慣れで、根本的に何かを誤解していると思うからです。

と入力すると(Character/isWhitespace \a)、 「名前空間があり、その中に という関数があることはわかっています。その関数を呼び出して渡したい」と言っていると思いますCharacterisWhitespace\a

このメンタル モデルでは、Clojure が「この関数が受け入れない引数の型を指定すると、関数が存在しないふりをする」と言っているように見えるため、上記の結果はわかりにくいものです。たとえば、「ブロックをブレンドすることは許可されていません。試してみると、Blender DoesntExist エラーが発生します。」これは奇妙です。

いくつかの答えはそれを暗示しているようです

  • 名前は、Clojure が関数を検索するために使用するものの一部Character/isWhitespaceにすぎず、他の部分は引数の型です。(さらに検索を行いました。これはおそらくマルチメソッドですか?)
  • メソッドが Java クラスで検索されていますか?

素晴らしい答えは、私にとってこのプロセスを明確にするでしょう。

4

4 に答える 4

10

tl;dr

clojure コンパイラーは、Java 相互運用クラス メソッドの一致するシグネチャを見つけるためにリフレクションに依存しており、何も見つからない場合は独自の例外を発生させます。

この場合、IllegalArgumentExceptionは正しく発生しnoMethodReportますが、混乱を招くエラー メッセージが表示されます。

そして、これはgithub リポジトリでそれを担当するソース コードです。clojure

ロングバージョン

まず、Java 相互運用解析のウォークスルー。

clojure パーサーが.ドット マクロを見つけると、HostExprパーサーは解析を処理し、2 番目の引数がシンボルかクラスかを判断しようとします。

それがクラスである場合、それは呼び出されているそのクラスの静的メソッドであると想定され、解析が続行されStaticMethodExprます。

パーサー内で最初に行うことは、クラスのリフレクションによってメソッドを見つけようとすることです。

  List methods = Reflector.getMethods(c, args.count(), methodName, true);
  if(methods.isEmpty())
      throw new IllegalArgumentException("No matching method: " + methodName);

適切に検出され、その時点で例外は発生しません

次に、見つかったメソッドにパラメーターを追加します。

  java.lang.reflect.Method m = (java.lang.reflect.Method) methods.get(i);
  params.add(m.getParameterTypes());

その後、一致するメソッド シグネチャ インデックスを見つけようとします。

  methodidx = getMatchingParams(methodName, params, args, rets);

この場合、「-1」を返し、methodnull のままになります。そして、それは解析段階です。

評価時間...

次に、invokeStaticMethodが呼び出されると、'isWhitespace' の 2 つの一致する署名を適切に検索する をgetMethods呼び出します。Reflector.java

そして最後に、関数内で表示されている紛らわしいメッセージ:

 static Object invokeMatchingMethod(String methodName, List methods, Object target, Object[] args)

見つかったメソッドは、適切な署名を持つメソッドを見つけようとして、パラメーターの一致についてテストされます。

 for(Iterator i = methods.iterator(); i.hasNext();)
   {
    m = (Method) i.next();
    Class[] params = m.getParameterTypes();
    if(isCongruent(params, args))

一致する署名が見つからない場合、例外が発生します

if(m == null)
   throw new IllegalArgumentException(noMethodReport(methodName,target));

したがって、答えは、clojure コンパイラーがメソッドの一致するシグネチャを見つけるためにリフレクションに依存しており、何も見つからない場合は独自の例外を発生させているということです。

この場合、IllegalArgumentExceptionは正しく発生しnoMethodReportますが、混乱を招くエラー メッセージが表示されます。

于 2013-10-25T14:04:00.417 に答える
7

Character/isWhitespaceJava メソッド (java.lang.Characterクラスの静的メソッド) です。Java メソッドを呼び出す構文の例については、 Java 相互運用を参照してください。

通常の Clojure 関数は名前だけで定義されますが、Java メソッドは、名前とパラメーターの数と型で構成されるシグネチャによって定義されます。

CharacterクラスisWhitespaceで定義されているメソッドの唯一のバリアントはとです。したがって、文字列で呼び出すための「一致する方法はありません」。isWhitespace(char ch)isWhitespace(int codepoint)isWhitespace

于 2013-10-25T17:00:39.083 に答える
3

"" は文字ではなく型文字列であるためです。

    user=> (type \a)
    java.lang.Character
    user=> (type "")
    java.lang.String

文字列 (Java) クラスには「isWhitespace」メソッドがありませんが、「文字」クラスにはあります。ドライバーで釘を打ち込むことはできません。

そこにはいくつかのヒントがあります:

Java Character クラスで空文字を表現する方法

"" は空の文字列です。しかし、「空の」文字の表現はありません。文字 "\0" は次のことを行いますが:

      user=> (Character/isWhitespace \0)
      false

そして isWhitespace 文字のドキュメント:

http://docs.oracle.com/javase/6/docs/api/java/lang/Character.html#isWhitespace%28char%29

次のように述べています。

「U+0000 から U+FFFF までの文字セットは、Basic Multilingual Plane (BMP) と呼ばれることがあります。コード ポイントが U+FFFF より大きい文字は、補助文字と呼ばれます。Java 2 プラットフォームでは、UTF-16 を使用します。 char 配列および String および StringBuffer クラスでの表現. この表現では、補助文字は char 値のペアとして表され、最初は上位サロゲート範囲 (\uD800-\uDBFF) から、2 番目は下位サロゲート範囲 (\uD800-\uDBFF) からです。サロゲート範囲 (\uDC00-\uDFFF)」。空引用符が該当しない。

つまり、 isWhitespace メソッドには空の文字列を「理解」する方法がありません。

さらに、clojure Java interlop doc http://clojure.org/java_interopから:

フィールドまたはメソッドのメンバーにアクセスするための推奨される慣用的な形式は、上記のとおりです。インスタンス メンバー フォームは、フィールドとメソッドの両方で機能します。これらはすべて、マクロ展開時にドット演算子 (後述) の呼び出しに展開されます。

そうタイピング

      (Character/isWhitespace "")

に展開します

       (. Classname instanceMember instance args*) 

       (. Character isWhitespace "")

エラーの原因。

       user=>  (. Character isWhitespace "")
       java.lang.IllegalArgumentException: No matching method found: isWhitespace (NO_SOURCE_FILE:0)

確認するには clojure のソース コードを確認する必要がありますが、私の推測では、これは下にある可能性のある動的な Java コンパイルに由来するものです。

  public class toto {

     public toto ()
     {
        Character.isWhitespace("");
     }

  }

それから:

  javac toto.class

  toto.java:5: error: no suitable method found for isWhitespace(String)
  Character.isWhitespace("");
         ^
  method Character.isWhitespace(int) is not applicable
  (actual argument String cannot be converted to int by method invocation conversion)
  method Character.isWhitespace(char) is not applicable
  (actual argument String cannot be converted to char by method invocation conversion)
  1 error
于 2013-10-25T12:56:58.597 に答える
2

isWhitespace引数として文字列をCharacter受け入れる apiのようなメソッドはありません。isWhitespaceメソッドはintorのみをchar引数として取ります。

于 2013-10-25T12:56:19.960 に答える