带有隐式参数的函数在没有它的情况下也能工作。为什么?
Function with an implicit parameter works without it. Why?
使用 Scala REPL,我定义了一个函数,该函数将 Int
作为其第一个参数,并将具有此签名 Int => Int
的函数作为第二个 implicit参数:
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 to Int函数从何而来?
REPL 报告没有定义隐式:
scala> :impl
No implicits have been imported other than those in Predef.
scala.Predef 中定义了一堆隐式,无需明确限定即可在所有 Scala 编译单元中访问,其中之一是
implicit def int2Integer(x: Int): java.lang.Integer = x.asInstanceOf[java.lang.Integer]
如果您查看 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
隐式就是为此目的而设计的。编译器将搜索是否有任何隐式定义对象可用。如果找到,则将使用它们。 scala 提供了许多隐式定义对象。您还可以将自定义对象定义为隐式,如果它们在您的代码范围内,将被使用。
查看文档
https://docs.scala-lang.org/tour/implicit-parameters.html
doer 之所以有效,是因为它接受隐式参数,因此在 Predef 中可用。 Predef 自动导入到 Scala 作用域。看起来使用的函数是 int2Integer。
Predef 包含一个 implicit evidence that one type is a subtype of another: A <:< B
。每种类型都是其自身的子类型,因此 implicitly[Int <:< Int]
有效。 <:<
class 扩展函数 A => B
。这就是 implicitly[Int => Int]
也有效的原因。
Int
和 java.lang.Integer
是不同的东西,没有任何子类型关系,所以这些 int2Integer
隐式与它无关。
如果您有最新 Scala 版本的 REPL,您可以输入
scala> doer(4) //print
然后按 tab 键而不是 enter。它将向您显示代码的脱糖版本 doer(4)(scala.Predef.$conforms[Int])
,其中所有隐式都已显式填充。
使用 Scala REPL,我定义了一个函数,该函数将 Int
作为其第一个参数,并将具有此签名 Int => Int
的函数作为第二个 implicit参数:
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 to Int函数从何而来? REPL 报告没有定义隐式:
scala> :impl
No implicits have been imported other than those in Predef.
scala.Predef 中定义了一堆隐式,无需明确限定即可在所有 Scala 编译单元中访问,其中之一是
implicit def int2Integer(x: Int): java.lang.Integer = x.asInstanceOf[java.lang.Integer]
如果您查看 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
隐式就是为此目的而设计的。编译器将搜索是否有任何隐式定义对象可用。如果找到,则将使用它们。 scala 提供了许多隐式定义对象。您还可以将自定义对象定义为隐式,如果它们在您的代码范围内,将被使用。
查看文档 https://docs.scala-lang.org/tour/implicit-parameters.html
doer 之所以有效,是因为它接受隐式参数,因此在 Predef 中可用。 Predef 自动导入到 Scala 作用域。看起来使用的函数是 int2Integer。
Predef 包含一个 implicit evidence that one type is a subtype of another: A <:< B
。每种类型都是其自身的子类型,因此 implicitly[Int <:< Int]
有效。 <:<
class 扩展函数 A => B
。这就是 implicitly[Int => Int]
也有效的原因。
Int
和 java.lang.Integer
是不同的东西,没有任何子类型关系,所以这些 int2Integer
隐式与它无关。
如果您有最新 Scala 版本的 REPL,您可以输入
scala> doer(4) //print
然后按 tab 键而不是 enter。它将向您显示代码的脱糖版本 doer(4)(scala.Predef.$conforms[Int])
,其中所有隐式都已显式填充。