views:

81

answers:

1

Hello.

Could anybody explain me following situation with Scala implicit conversions mechanism. There is a code:

object Main {
  implicit val x:Int => String = v => "val"
  implicit def y(v:Int) = "def"

  def p(s:String) = print(s)

  def main(args: Array[String]): Unit = {
      p(1)
  }
}

This code prints "val". But when I comment second line:

//implicit val x:Int => String = v => "val"

code prints "def".

So both implicit conversions (x and y) are possible in this situation. There is a Non-Ambiguity Rule - an implicit conversion is only inserted if there is no other possible conversion to insert. According to this rule this code shouldn't be compiled at all. But the code is successfully compiled and executed. What I don't understand?

Thanks.

+7  A: 

The reason for this is stated in the Scala Language Specification section 6.26.2.

Before the method can be treated as a function it needs to be converted to one by performing eta-expansion. Thus one more implicit conversion would have to be applied and so the val is chosen.

UPDATE: removed flawed example.

Evaluation of a method without parameters is always performed implicitly.

Moritz
Hello Moritz. Thanks you for an answer. So when Scala compiler sees expression whose type does not match an expected type, it looks for implicit conversions of type T=>F, if such conversions weren't found, compiler tries to perform Eta Expansion or Empty Application on available method expressions (the word “Otherwise” in Scala Language Specification tells that this action will be performed after). Whether I understood it all?
Artem Bergkamp
But in your example if I comment //implicit val t = "World", code wouldn't be compiled. It seems that Empty Application isn't taken into consideration by Scala compiler here.
Artem Bergkamp
Empty application is AFAICT actually not used when the compiler searches for implicit conversions but only for filling in other implicit parameters. If you write `implicit def i2s(): Int => String = _.toString` this will not be considered as a candidate for a conversion from `String` to `Int`. Apart from that it is correct - the conversions in the list in 6.26.2 are tried from top to bottom if the value can not be evaluated directly.
Moritz
Forget that one: I got it mixed up. Empty application is on the value itself. It means nothing more than that you can discard the trailing `()`s. E.g. `x.getY` gets translated to `x.getY()`. Sorry for that confusion.
Moritz