10

部分的に適用してカリー化で使用しようとしている 2 つのパラメーター リストを持つ関数があります。2 番目のパラメーター リストには、すべて既定値を持つ (ただし、暗黙的ではない) 引数が含まれます。このようなもの:

 def test(a: Int)(b: Int = 2, c: Int = 3) { println(a + ", " + b + ", " + c); }

これで、次はすべて問題ありません。

 test(1)(2, 3);
 test(1)(2);
 test(1)(c=3);
 test(1)();

今私が定義した場合:

 def partial = test(1) _;

次に、次のことができます。

 partial(2, 3);

次のように、「部分的」で一部/すべての引数を省略できない理由を誰かが説明できますか:

 partial(2);
 partial(c=3);
 partial();

「部分的」と書くことは、本質的に「test(1)」と同じように振る舞うべきではありませんか? 誰かがこれを達成する方法を見つけるのを手伝ってもらえますか?

助けてください、私は必死です!

編集- 24 時間以内に自分の質問に答えることができないため、ここに自分の回答を投稿します。

これは、これまでのところ自分でできる最善のことです。

class Test2(val a: Int) {
   def apply(b: Int = 2, c: Int = 3) { println(a + ", " + b + ", " + c); }
}

def test2(a: Int) = new Test2(a);
def partial2 = test2(1); // Note no underscore

test2(1)(2, 3);
test2(1)(2);
test2(1)(c=3);
test2(1)();

partial2(2, 3)
partial2(2);
partial2(c=3);
partial2();

このように動作します...

4

3 に答える 3

6

型推論エンジンはpartial、次に来るものの型を与えます。すなわち、エータ展開test(1) _. partialたとえば、 type を持っている REPL で見ることができますが、(Int, Int) => Unittypetestを持ってい(a: Int)(b: Int,c: Int)Unitます。eta 展開の結果はFunctionオブジェクトであり、引数名を持ちません (Function匿名パラメーターで定義できるため)。

これを修正するにはpartial、次のように定義する必要があります。

def partial(b: Int = 2, c: Int = 3) = test(1)(b,c)

testおそらく、との両方がそれらに到達できるデフォルト値を除外して、partialそれらが等しく保たれるようにすることをお勧めします。しかし、新しいオブジェクトの作成などの余分なオーバーヘッドを導入することなく、パラメーターの名前を繰り返すことを避けるためのトリックは知りません。

于 2011-04-15T12:05:35.127 に答える
4

これは、これまでのところ自分でできる最善のことです。

class Test2(val a: Int) {
   def apply(b: Int = 2, c: Int = 3) { println(a + ", " + b + ", " + c); }
}

def test2(a: Int) = new Test2(a);
def partial2 = test2(1); // Note no underscore

test2(1)(2, 3);
test2(1)(2);
test2(1)(c=3);
test2(1)();

partial2(2, 3)
partial2(2);
partial2(c=3);
partial2();

このように動作します...

于 2011-04-16T16:03:58.890 に答える
2

あなたのコメントに続いて、それを書くためのよりコンパクトな方法があります:

def test(a: Int) = new {
  def apply(b: Int = 2, c: Int = 3) {
    println(a + ", " + b + ", " + c)
  }
}

これはあなたの提案よりも少しコンパクトですが、内部への呼び出しはapply構造型と同様にリフレクションを介して発生するため、効率が低下します。実際、 の戻り値の型testは構造型です。

 java.lang.Object{def apply(b: Int,c: Int): Unit; def apply$default$1: 
 Int @scala.annotation.unchecked.uncheckedVariance; def apply$default$2: Int 
 @scala.annotation.unchecked.uncheckedVariance}
于 2011-04-15T14:12:32.420 に答える