使用Scala REPL,我定义了一个函数,它将Int
作为其第一个参数,并使用此签名Int => Int
作为第二个隐式参数:
scala> def doer(i: Int)(implicit a: Int => Int): Int = a(i)
doer: (i: Int)(implicit a: Int => Int)Int
为什么在不提供隐式参数的情况下运行此函数?
scala> doer(4)
res1: Int = 4
Int到Int函数的隐式Int来自何处? REPL报告没有定义任何含义:
scala> :impl
No implicits have been imported other than those in Predef.
答案 0 :(得分:2)
Predef包含implicit evidence,其中一种类型是另一种类型的子类型:A <:< B
。每种类型都是自身的子类型,因此implicitly[Int <:< Int]
起作用。此<:<
类扩展了函数A => B
。这就是implicitly[Int => Int]
也起作用的原因。
Int
和java.lang.Integer
是不同的事物,没有任何子类型关系,所以这些int2Integer
暗示与它无关。
如果你有最近Scala版本的REPL,你可以输入
scala> doer(4) //print
然后按Tab键而不是输入。它将向您显示代码的desugared版本doer(4)(scala.Predef.$conforms[Int])
,并明确填写所有含义。
答案 1 :(得分:0)
在scala.Predef中定义了大量的implicits,它们可以在没有明确限定的所有Scala编译单元中访问,其中一个是
implicit def int2Integer(x: Int): java.lang.Integer = x.asInstanceOf[java.lang.Integer]
答案 2 :(得分:0)
如果检查Predef源代码,可以看到很多隐式函数。编译器只会选择一个兼容的。
一些例子:
implicit def booleanArrayOps(xs: Array[Boolean]): ArrayOps[Boolean] = new ArrayOps.ofBoolean(xs)
implicit def byteArrayOps(xs: Array[Byte]): ArrayOps[Byte] = new ArrayOps.ofByte(xs)
implicit def charArrayOps(xs: Array[Char]): ArrayOps[Char] = new ArrayOps.ofChar(xs)
implicit def doubleArrayOps(xs: Array[Double]): ArrayOps[Double] = new ArrayOps.ofDouble(xs)
implicit def floatArrayOps(xs: Array[Float]): ArrayOps[Float] = new ArrayOps.ofFloat(xs)
implicit def intArrayOps(xs: Array[Int]): ArrayOps[Int] = new ArrayOps.ofInt(xs)
implicit def longArrayOps(xs: Array[Long]): ArrayOps[Long] = new ArrayOps.ofLong(xs)
implicit def refArrayOps[T <: AnyRef](xs: Array[T]): ArrayOps[T] = new ArrayOps.ofRef[T](xs)
implicit def shortArrayOps(xs: Array[Short]): ArrayOps[Short] = new ArrayOps.ofShort(xs)
implicit def unitArrayOps(xs: Array[Unit]): ArrayOps[Unit] = new ArrayOps.ofUnit(xs)
// "Autoboxing" and "Autounboxing" ---------------------------------------------------
implicit def byte2Byte(x: Byte) = java.lang.Byte.valueOf(x)
implicit def short2Short(x: Short) = java.lang.Short.valueOf(x)
implicit def char2Character(x: Char) = java.lang.Character.valueOf(x)
implicit def int2Integer(x: Int) = java.lang.Integer.valueOf(x)
implicit def long2Long(x: Long) = java.lang.Long.valueOf(x)
implicit def float2Float(x: Float) = java.lang.Float.valueOf(x)
implicit def double2Double(x: Double) = java.lang.Double.valueOf(x)
implicit def boolean2Boolean(x: Boolean) = java.lang.Boolean.valueOf(x)
implicit def Byte2byte(x: java.lang.Byte): Byte = x.byteValue
implicit def Short2short(x: java.lang.Short): Short = x.shortValue
implicit def Character2char(x: java.lang.Character): Char = x.charValue
implicit def Integer2int(x: java.lang.Integer): Int = x.intValue
implicit def Long2long(x: java.lang.Long): Long = x.longValue
implicit def Float2float(x: java.lang.Float): Float = x.floatValue
implicit def Double2double(x: java.lang.Double): Double = x.doubleValue
implicit def Boolean2boolean(x: java.lang.Boolean): Boolean = x.booleanValue
答案 3 :(得分:0)
隐含是为此目的而设计的。编译器将搜索是否有任何隐式定义对象。如果它发现那么将使用它们。 scala提供了许多隐式定义对象。您还可以将自定义对象定义为隐式对象,如果它们在您的代码范围内,则将使用它们。
查看文档 https://docs.scala-lang.org/tour/implicit-parameters.html
doer 有效,因为它接受隐式参数,因此它在Predef中可用。 Predef会自动导入scala范围。看起来使用的函数是 int2Integer 。