Scala - Currying and default arguments

后端 未结 3 838
旧巷少年郎
旧巷少年郎 2020-12-31 13:12

I have a function with two parameter lists that I am trying to partially apply and use with currying. The second parameter list contains arguments that all have default valu

相关标签:
3条回答
  • 2020-12-31 13:51

    This is the best I could do myself so far:

    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();
    

    This way it works...

    0 讨论(0)
  • 2020-12-31 14:07

    Following up on your comment, here's a more compact way to write it:

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

    This is a bit more compact than your proposal, but is less efficient, as any call to the inner apply will occur through reflection, as with structural types. Actually, the return type of test is a structural type:

     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}
    
    0 讨论(0)
  • 2020-12-31 14:09

    The type inference engine gives to partial the type of what comes next; i.e., the eta expansion test(1) _. You can see e.g. in the REPL that partial has type (Int, Int) => Unit, whereas test has type (a: Int)(b: Int,c: Int)Unit. The result of the eta expansion is a Function object, which does not carry any argument names with it (as it is possible to define Function with anonymous parameters).

    To fix this, you have to define partial as follows:

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

    Maybe you'll want to factor out the default values where both test and partial can reach them to make sure they stay equal. But I know of no trick to avoid repeating the names of the parameters without introducing extra overhead like creating of new objects, etc.

    0 讨论(0)
提交回复
热议问题