传递和使用隐式函数而不定义它
passing & using an implicit function without defining it
我没有在任何地方定义函数 ev
。那么,下面的代码是如何工作的呢?隐式是否必须在范围内的某处定义才能使用?
def same[T, U](x: U)(implicit ev: U => T): T = {ev(x)}
same(2) // 2
任何时候你有这样的问题,一个好的开始是在 REPL 中使用 Scala 反射 API 来询问编译器发生了什么:
scala> import scala.reflect.runtime.universe.{ reify, showCode }
import scala.reflect.runtime.universe.{reify, showCode}
scala> def same[T, U](x: U)(implicit ev: U => T): T = ev(x)
same: [T, U](x: U)(implicit ev: U => T)T
scala> showCode(reify(same(2)).tree)
res0: String = $read.same(2)(Predef.$conforms)
因此 ev
由 Predef.$conforms
, an implicit method that will give you an instance of A <:< A
for any A
, where <:<
扩展 Function1
.
提供
这就是一条线索。弄清楚其余部分需要稍微考虑一下类型推断。当您调用 same(2)
时,编译器发现表达式 2
的类型为 Int
,并推断出 U
是 Int
。接下来它需要弄清楚 T
是什么,为此它会为某些类型 x
.
寻找从 Int
到 x
的隐式函数
这就是 $conforms
的用武之地。它是范围内唯一的此类方法,因此编译器选择了它,这意味着 ev
的类型为 Int => Int
和 T
必须是 Int
,你就完成了。
我没有在任何地方定义函数 ev
。那么,下面的代码是如何工作的呢?隐式是否必须在范围内的某处定义才能使用?
def same[T, U](x: U)(implicit ev: U => T): T = {ev(x)}
same(2) // 2
任何时候你有这样的问题,一个好的开始是在 REPL 中使用 Scala 反射 API 来询问编译器发生了什么:
scala> import scala.reflect.runtime.universe.{ reify, showCode }
import scala.reflect.runtime.universe.{reify, showCode}
scala> def same[T, U](x: U)(implicit ev: U => T): T = ev(x)
same: [T, U](x: U)(implicit ev: U => T)T
scala> showCode(reify(same(2)).tree)
res0: String = $read.same(2)(Predef.$conforms)
因此 ev
由 Predef.$conforms
, an implicit method that will give you an instance of A <:< A
for any A
, where <:<
扩展 Function1
.
这就是一条线索。弄清楚其余部分需要稍微考虑一下类型推断。当您调用 same(2)
时,编译器发现表达式 2
的类型为 Int
,并推断出 U
是 Int
。接下来它需要弄清楚 T
是什么,为此它会为某些类型 x
.
Int
到 x
的隐式函数
这就是 $conforms
的用武之地。它是范围内唯一的此类方法,因此编译器选择了它,这意味着 ev
的类型为 Int => Int
和 T
必须是 Int
,你就完成了。