Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Scala implicit conversion on call-by-name parameter works differently depending on the function is overloaded or not

Let's see the code below:

import scala.language.implicitConversions
class Foo
implicit def int2Foo(a: => Int): Foo = new Foo
def bar(foo: Foo) = {}
def bar(foo: Boolean) = {}
bar {
  println("Hello")
  64
}

This code does not print anything, because the block contains println("Hello") treated as => Int and it is converted to Foo by int2Foo. But the surprising thing is happen if we omit the overloaded function bar(foo: Boolean)

import scala.language.implicitConversions
class Foo
implicit def int2Foo(a: => Int): Foo = new Foo
def bar(foo: Foo) = {}
bar {
  println("Hello")
  64
}

This prints Hello because it evaluates the block, and only the last statement, 64 in this case, is treated as a call-by-name parameter. I cannot understand what kind of rationale exists behind of this difference.

like image 871
pocorall Avatar asked Jul 07 '15 14:07

pocorall


1 Answers

I think the Scala specification is ambiguous about how implicit views should be applied here. In other words, both of the following interpretations of the statement conform to the spec:

bar { println("Hello"); int2Foo(64) }
bar { int2Foo({ println("Hello"); 64 }) }

Of course, it is extremely counterintuitive for an unrelated overload to affect this behavior. It seems to me that the behavior, although ambiguous, should at least be consistent. This must be an implementation detail of the compiler interactions between overload resolution, by-name parameters, and implicit views. I have filed SI-9386 to address the issue.

like image 168
Ben Reich Avatar answered Oct 15 '22 10:10

Ben Reich