简体   繁体   中英

Multiple parameters lists and default arguments

Compiling this code:

class Test {

  def f(arg: Int)(defaultArg: String => Unit = println): Unit = ???

  f(42)
}

fails with

missing argument list for method f in class Test [error] Unapplied methods are only converted to functions when a function type is expected. [error] You can make this conversion explicit by writing `f _` or `f(_)(_)` instead of `f`. [error] f(42) [error] ^ [error] one error found

Why does it fail? Does it introduce ambiguity? Is it possible to make it work w/o resorting to single parameters list?

The correct syntax for your case is the following:

f(42)()

You can make call to f(42) work by defining defaultArg as implicit:

def f(arg: Int)(implicit defaultArg: String => Unit = println): Unit = ???

Then you can call it:

f(42)

So you are passing a Int argument to a method and a function that can print it. Now when you say f(42) the compiler would see that the function can be applied to the Int and result in another function. That is it see this is a case of partially applied function. So when you make the call f(42) the result is another function.So the compiler complains saying that you should either pass in the second argument or treat this result as a partially applied function.

Consider the following code,

val ptln1:String=>Unit = System.out.println _ //Doing this to show the type of the println function
def f(arg: Int)(defaultArg: String => Unit = ptln1): Unit = ???
val t = f(42)()

As you can see i have written the types explicitly so it makes sense.
So now you could either pass the function using implicits as below,

def f(arg: Int)(implicit defaultArg: String => Unit = println _): Unit = ???
f(42)()

Or this without implicits ,

  def f(arg: Int)(defaultArg: String => Unit = println _): Unit = ???
  val t = f(42)()

Also consider the following optionally if i use a self defined function instead of the println . Maybe this will make it clearer.

implicit def testPrint(str:String):Unit = ???

   def f(arg: Int)(implicit defaultArg: String => Unit = testPrint): Unit = ???

   val t = f(42)

Or without implicits ,

   def testPrint(str:String):Unit = ???

   def f(arg: Int)(defaultArg: String => Unit = testPrint): Unit = ???

   val t = f(42)()

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM