Scala 隐式转换按名称调用参数的工作方式不同,具体取决于函数是否重载
Scala implicit conversion on call-by-name parameter works differently depending on the function is overloaded or not
让我们看下面的代码:
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
}
此代码不打印任何内容,因为该块包含被视为 => Int
的 println("Hello")
,并由 int2Foo
转换为 Foo
。但是如果我们省略重载函数 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
}
这会打印 Hello
因为它计算块,并且只有最后一个语句,在这种情况下,64
被视为按名称调用的参数。我无法理解这种差异背后存在什么样的理由。
我认为 Scala 规范对于此处应如何应用隐式视图含糊不清。换句话说,语句的以下两种解释都符合规范:
bar { println("Hello"); int2Foo(64) }
bar { int2Foo({ println("Hello"); 64 }) }
当然,不相关的重载影响这种行为是非常违反直觉的。在我看来,这种行为虽然模棱两可,但至少应该是一致的。这必须是重载解析、按名称参数和隐式视图之间的编译器交互的实现细节。我已经提交 SI-9386 来解决这个问题。
让我们看下面的代码:
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
}
此代码不打印任何内容,因为该块包含被视为 => Int
的 println("Hello")
,并由 int2Foo
转换为 Foo
。但是如果我们省略重载函数 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
}
这会打印 Hello
因为它计算块,并且只有最后一个语句,在这种情况下,64
被视为按名称调用的参数。我无法理解这种差异背后存在什么样的理由。
我认为 Scala 规范对于此处应如何应用隐式视图含糊不清。换句话说,语句的以下两种解释都符合规范:
bar { println("Hello"); int2Foo(64) }
bar { int2Foo({ println("Hello"); 64 }) }
当然,不相关的重载影响这种行为是非常违反直觉的。在我看来,这种行为虽然模棱两可,但至少应该是一致的。这必须是重载解析、按名称参数和隐式视图之间的编译器交互的实现细节。我已经提交 SI-9386 来解决这个问题。