6

I can the require method in Scala's Predef class with a String as second argument, e.g.

require ("foo" == "bar", "foobar")

First a thought the require method is overloaded for different parameters as second argument. But it is not. The Signature of the require method (Scala 2.9.1) is:

require(requirement: Boolean, message: ⇒ Any): Unit

Why is the above method call possible ?

4

4 に答える 4

22

私はその質問を完全には理解していませんが、ここに少し説明があります。requireにオーバーロードされたバージョンが1つありPredefます:

def require(requirement: Boolean) //...
def require(requirement: Boolean, message: => Any) //...

2つ目は、タイプが原因で少し混乱しmessage: => Anyます。それが単純であるならば、それはおそらくより簡単でしょう:

def require(requirement: Boolean, message: Any) //...

2番目のパラメーターはもちろん、アサーションが満たされない場合にエラーメッセージに追加されると想定されるメッセージです。あなたはタイプmessageであるべきだと想像することができますが、あなたと一緒に簡単に書くことができます:StringAny

require(x == 4, x)

と等しくない場合、x(タイプの)の実際の値がエラーメッセージに追加されます。そのため、任意の値を許可するために選択されました。Int4Any

しかし、: =>一部はどうですか?これは名前による呼び出しと呼ばれ、基本的に次のことを意味します。アクセス時にこのパラメーターを評価します。次のスニペットを想像してみてください。

require(list.isEmpty, list.size)

この場合、が空であることを確認する必要があります。list空でない場合は、実際のlistサイズをエラーメッセージに追加します。ただし、通常の呼び出し規約では、メソッドを呼び出す前にlist.sizeパーツを評価する必要があります。これは無駄になる可能性があります。名前による呼び出しの規則では、は最初に使用されたとき、つまりエラーメッセージがコンストラクターである場合にのみ評価されます(必要な場合)。list.size

于 2012-05-20T11:50:23.600 に答える
4

このrequireメソッドは、Predefscalaがデフォルトのパラメーター(2.8で導入)を持つ前に存在していたため、特定のパラメーターのデフォルトの動作が必要な場合は、オーバーロードが唯一のオプションでした。メッセージに示されているように、2番目の引数は何でもかまいません。これは、スローされた(スローされた場合、つまり要件が失敗した場合)の(メソッドmessageを呼び出すことによって)使用されます。toStringIllegalArgumentException

引数は実際には名前による呼び出しであることに注意してください。つまり、として宣言されます。これは、要件が失敗した場合にのみ評価される=> Anyことを意味します。

これにより、オブジェクトの作成という形でパフォーマンスが低下しますが、メッセージの作成に費用がかかる場合(おそらく、データ構造へのO(n)アクセスが必要になる場合)に役立つことがあります。

于 2012-05-20T11:49:36.360 に答える
2

問題は、署名が関数でなければならないと言っているのに、なぜ文字列が2番目の引数の有効な型であるのかということですmessage: => Any

署名はそれを言いません。署名は、2番目の引数がタイプAnyであり、このパラメーターが名前で渡されることを示しています。

「名前による」は、関数を意味しない=>接頭辞記号で示されます。関数は、常に入力パラメーター=>結果タイプとして示されます。Function0() => type

「値で」および「名前で」パラメータを検索します。

于 2012-05-21T01:42:09.340 に答える
-1

答えは非常に簡単です:あなたはの2番目の引数を期待しています

require(boolean: Boolean, message: => Any): Unit

関数ではないのに、Anyの関数になり、なぜ関数が機能するのかを尋ねます。String

これに分解してください:固定String関数に他なりません

  1. 引数を取りません
  2. ()括弧を呼び出す必要はありません
  3. すべての呼び出しで同じ結果が得られます

実際、Scalaでは次の2つのステートメントが同等です。

def x: String = "ABC" // const value, even though 'def' implies a function
val x: String = "ABC"

したがって、=> Anyはで満足していると言うかもしれませんString

于 2012-05-20T12:03:27.133 に答える