为什么在 scala 中允许 'val arr: Int => Int = Array(1,2,3)'
Why 'val arr: Int => Int = Array(1,2,3)' is allowed in scala
使用以下代码:
object Foo {
val arr: Int => Int = Array(1,2,3)
}
我们可以调用Foo.arr(1)
,然后得到2
。但是,对象 Foo
中的 arr
应该是 Function
。 arr
是 Class WrappedArray$ofInt
的实例,显然不是 Function
.
我想也许原因是 WrappedArray$ofInt
implements apply(i: Int)
,因为调用 Array(1,2,3)(1)
将被翻译成 Array(1,2,3).apply(1)
。但是下面的代码会报错:
class Bar {
def apply(i: Int): Int = {
Array(1,2,3)(i)
}
}
object Foo {
val arr: Int => Int = new Bar() //Type mismatch:
// Required: Int => Int
// Found: Bar
}
现在,为什么 Scala 允许 val arr: Int => Int = Array(1,2,3)
?
REPL 是探索此类情况的绝佳工具。
所以,让我们从代码开始:
val arr: Int => Int = Array(1,2,3)
在 Scala 中,唯一可行的方法是 Array[Int] <: Int => Int
或者是否存在从 Array[Int]
到子类型的隐式转换共 Int => Int
我们可以很容易地检查第一个不是这种情况:
implicitly[Array[Int] <:< Int => Int]}
产生:
error: No implicit view available from Array[Int] <:< Int => Int.
因此,它必须是第二个;我们也可以确认它在做:
implicitly[Array[Int] => (Int => Int)]
// val res: Array[Int] => (Int => Int) = $Lambda65/0x00000008406ff040@4dac40b
顺便说一句,如果我们将原始行粘贴到 REPL 中,我们会得到以下输出:
val foo: Int => Int = Array(1,2,3)
// val foo: Int => Int = ArraySeq(1, 2, 3)
所以我们已经可以看到转换发生了,结果是 ArraySeq[Int]
(如果你检查 Scaladoc 你可以看到 class确实继承了Int => Int
).
如果您想更深入地学习,可以使用 reify
import scala.reflect.runtime.universe.reify
reify { val foo: Int => Int = Array(1,2,3) }
产生以下输出:
val res: reflect.runtime.universe.Expr[Unit] =
Expr[Unit]({
val foo: Function1[Int, Int] = Predef.wrapIntArray(Array.apply(1, 2, 3));
()
})
然后是 docs again we can see that it indeed returns an ArraySeq
.
使用以下代码:
object Foo {
val arr: Int => Int = Array(1,2,3)
}
我们可以调用Foo.arr(1)
,然后得到2
。但是,对象 Foo
中的 arr
应该是 Function
。 arr
是 Class WrappedArray$ofInt
的实例,显然不是 Function
.
我想也许原因是 WrappedArray$ofInt
implements apply(i: Int)
,因为调用 Array(1,2,3)(1)
将被翻译成 Array(1,2,3).apply(1)
。但是下面的代码会报错:
class Bar {
def apply(i: Int): Int = {
Array(1,2,3)(i)
}
}
object Foo {
val arr: Int => Int = new Bar() //Type mismatch:
// Required: Int => Int
// Found: Bar
}
现在,为什么 Scala 允许 val arr: Int => Int = Array(1,2,3)
?
REPL 是探索此类情况的绝佳工具。
所以,让我们从代码开始:
val arr: Int => Int = Array(1,2,3)
在 Scala 中,唯一可行的方法是 Array[Int] <: Int => Int
或者是否存在从 Array[Int]
到子类型的隐式转换共 Int => Int
我们可以很容易地检查第一个不是这种情况:
implicitly[Array[Int] <:< Int => Int]}
产生:
error: No implicit view available from Array[Int] <:< Int => Int.
因此,它必须是第二个;我们也可以确认它在做:
implicitly[Array[Int] => (Int => Int)]
// val res: Array[Int] => (Int => Int) = $Lambda65/0x00000008406ff040@4dac40b
顺便说一句,如果我们将原始行粘贴到 REPL 中,我们会得到以下输出:
val foo: Int => Int = Array(1,2,3)
// val foo: Int => Int = ArraySeq(1, 2, 3)
所以我们已经可以看到转换发生了,结果是 ArraySeq[Int]
(如果你检查 Scaladoc 你可以看到 class确实继承了Int => Int
).
如果您想更深入地学习,可以使用 reify
import scala.reflect.runtime.universe.reify
reify { val foo: Int => Int = Array(1,2,3) }
产生以下输出:
val res: reflect.runtime.universe.Expr[Unit] =
Expr[Unit]({
val foo: Function1[Int, Int] = Predef.wrapIntArray(Array.apply(1, 2, 3));
()
})
然后是 docs again we can see that it indeed returns an ArraySeq
.