user3663882 user3663882 - 3 months ago 53
Scala Question

Method call (with implicit parameters) without parenthesis in scala

I'm trying to understand where implicit parameters come from. Here is the simple demonstration of generic type constraint implicit resolution:

class ImplicitTypeConstraint[+T](val t : T) {
def doSome1(implicit ev: T <:< Int) = println("Int value = " + ev(t))
def doSome2(implicit ev: T <:< Int, u : Unit) = println("Int value = " + ev(t))
def doSome3(u : Unit)(implicit ev: T <:< Int) = println("Int value = " + ev(t))
}


Now I tried this

val itc = new ImplicitTypeConstraint(10)
itc.doSome1 //compiles fine
itc.doSome1() //compile error, Cannot resolve reference doSome1 with such signature

itc.doSome2 //compile error, not enough arguments for method doSome2
itc.doSome2() //compile error, Cannot resolve reference doSome2 with such signature

itc.doSome3 //compile error, Cannot resolve reference doSome3 with such signature
itc.doSome3() //compiles fine


The question is, what is the difference between the signatures of
doSome1
and
doSome2
? I came from Java and I thought, that
foo()
will call a function which has no explicit parameters, but it seems that it looks for a function with one parameter of type
Unit
.

UPD: Itellij didn't show the error before I build the project explicitly. Both
doSome2()
and
doSome2
refuses to compile.

Answer

f() calls a method with an empty parameter list (and possibly with implicit parameters after this list). Neither doSome nor doSome2 have an empty parameter list, so of course itc.doSome() and itc.doSome2() don't compile. itc.doSome compiles because it calls the function with no parameter list, and implicit parameters are inserted. itc.doSome2 doesn't compile because there is no implicit Unit in scope.

In itc.doSome3(), () is the value of type Unit, not the method call parentheses. So it's actually itc.doSome3(()). The compiler should give a warning about this:

Warning:(15, 13) Adaptation of argument list by inserting () has been deprecated: this is unlikely to be what you want.
        signature: ImplicitTypeConstraint.doSome3(u: Unit)(implicit ev: <:<[T,Int]): Unit
  given arguments: <none>
 after adaptation: ImplicitTypeConstraint.doSome3((): Unit)
itc.doSome3();//
           ^