'Array[Int]'在scala中隐式转换为'Int => Int'的地方在哪里?
Where is the place that 'Array[Int]' is implicitly converted to 'Int => Int' in scala?
后面是一道题。
现在我们已经证明了 Array[Int]
可以隐式转换为 Int => Int
,但是 哪里有 发生的地方呢?
显然,Int => Int
是一个函数:
scala> var fun = (i: Int) => Array(1,2,3)(i)
fun: Int => Int = <function1>
而Array[Int]
是一个class:
scala> var arr = Array(1,2,3)
arr: Array[Int] = Array(1, 2, 3)
但是arr
可以赋值给fun
:
scala> fun = arr
fun: Int => Int = WrappedArray(1, 2, 3)
反之则不行:
scala> arr = fun
<console>:34: error: type mismatch;
found : Int => Int
required: Array[Int]
arr = fun
^
现在,隐式 转换发生的地方在哪里?
当您将 Array(1)
分配给 Int => Int
类型的 val
时,将调用隐式转换 scala.LowPriorityImplicits#wrapIntArray
。
它将Array
包装成ArraySeq
,然后实现Function1
或Int => Int
既然你有 WrappedArray
I'm guessing you have Scala 2.12 or earlier - Scala 2.13 has ArrayOps
.
存在从Array
到WrappedArray
的隐式转换(实际上是a whole family o conversions)。所以你有一个从 Array[T]
到 WrappedArray[T]
.
的隐式转换
现在,WrappedArray
实现了 Scala 的各种集合特征。其中之一是 Seq
实施 PartialFunction
(进而扩展 Function
)。这意味着 Scala 中的所有集合都是来自某个键的函数(Int
在序列的情况下,可能是其他的在 Map
s 的情况下)。这包括 WrappedArray
.
因此,您对 WrappedArray
的转换会自动将 Array[T]
转换为(a 的子类型)函数 Int => T
。
事实上,这就是为什么你应该避免将任何集合(或在 2.13 之前可隐式转换为集合的东西,如 Array
)放入隐式范围的原因:隐式范围中的集合自动成为隐式转换本身。此问题仅在 Scala 3 中得到解决,其中隐式转换变为 a separate subtype of Function
interface.
but where is the place that happens?
隐式转换在必要时发生,在本例中是在赋值本身。
看看我在另一个答案中的 reify
块:
val foo: Function1[Int, Int] = Predef.wrapIntArray(Array.apply(1, 2, 3));
这就是转换,调用方法:Predef
对象中的 wrapIntArray
。
Obviously, Int => Int is a Function:
And Array[Int] is a class:
But arr can be assigned to fun:
Conversely, it will not work:
看来你不知道/不明白 Scala functions
也是 objects
(Scala 是一个 object
,任何值都是 object
).
所以我们不能直接将一个Array[Int]
赋给一个应该是Int => Int
的值;因为 Array[Int]
不是 Int => Int
的子类型(如我之前的回答所示).
但是我们可以将 Array[Int]
转换为 ArraySeq[Int]
,它是 Int => Int
的子类型,因此我们可以进行赋值。
相反的方法不起作用,因为 Int => Int
不是 Array[Int]
也不是 ArraySeq[Int]
请注意,这只是基本子类型,Dog
是 Pet
的子类型,但 Pet
不是 Dog
的子类型
Which one is the class/trait related to Function[Int, Int]? I have checked the link you mentioned: sealed abstract class ArraySeq[+A] extends AbstractSeq[A] with IndexedSeq[A] with IndexedSeqOps[A, ArraySeq, ArraySeq[A]] with StrictOptimizedSeqOps[A, ArraySeq, ArraySeq[A]] with EvidenceIterableFactoryDefaults[A, ArraySeq, ClassTag] with Serializable
那些是类 / traits ArraySeq
直接扩展的,在Scaladoc link中有一个按钮可以看到所有的supper类型您会看到 (Int) => A
中的广告
编辑
The last question is which super type does the (Int) => A come from? There are too many types ArraySeq extended.
您需要遍历层级:
- immutable.ArraySeq 扩展 immutable.AbstractSeq
- immutable.AbstractSeq 扩展 immutable.Seq
- immutable.Seq 扩展 collection.Seq
- collection.Seq 扩展 PartialFunction[Int, A]
- PartialFunction[Int, A] extends Function1[Int, A]
现在我们已经证明了 Array[Int]
可以隐式转换为 Int => Int
,但是 哪里有 发生的地方呢?
显然,Int => Int
是一个函数:
scala> var fun = (i: Int) => Array(1,2,3)(i)
fun: Int => Int = <function1>
而Array[Int]
是一个class:
scala> var arr = Array(1,2,3)
arr: Array[Int] = Array(1, 2, 3)
但是arr
可以赋值给fun
:
scala> fun = arr
fun: Int => Int = WrappedArray(1, 2, 3)
反之则不行:
scala> arr = fun
<console>:34: error: type mismatch;
found : Int => Int
required: Array[Int]
arr = fun
^
现在,隐式 转换发生的地方在哪里?
当您将 Array(1)
分配给 Int => Int
类型的 val
时,将调用隐式转换 scala.LowPriorityImplicits#wrapIntArray
。
它将Array
包装成ArraySeq
,然后实现Function1
或Int => Int
既然你有 WrappedArray
I'm guessing you have Scala 2.12 or earlier - Scala 2.13 has ArrayOps
.
存在从Array
到WrappedArray
的隐式转换(实际上是a whole family o conversions)。所以你有一个从 Array[T]
到 WrappedArray[T]
.
现在,WrappedArray
实现了 Scala 的各种集合特征。其中之一是 Seq
实施 PartialFunction
(进而扩展 Function
)。这意味着 Scala 中的所有集合都是来自某个键的函数(Int
在序列的情况下,可能是其他的在 Map
s 的情况下)。这包括 WrappedArray
.
因此,您对 WrappedArray
的转换会自动将 Array[T]
转换为(a 的子类型)函数 Int => T
。
事实上,这就是为什么你应该避免将任何集合(或在 2.13 之前可隐式转换为集合的东西,如 Array
)放入隐式范围的原因:隐式范围中的集合自动成为隐式转换本身。此问题仅在 Scala 3 中得到解决,其中隐式转换变为 a separate subtype of Function
interface.
but where is the place that happens?
隐式转换在必要时发生,在本例中是在赋值本身。
看看我在另一个答案中的 reify
块:
val foo: Function1[Int, Int] = Predef.wrapIntArray(Array.apply(1, 2, 3));
这就是转换,调用方法:Predef
对象中的 wrapIntArray
。
Obviously, Int => Int is a Function:
And Array[Int] is a class:
But arr can be assigned to fun:
Conversely, it will not work:
看来你不知道/不明白 Scala functions
也是 objects
(Scala 是一个 object
,任何值都是 object
).
所以我们不能直接将一个Array[Int]
赋给一个应该是Int => Int
的值;因为 Array[Int]
不是 Int => Int
的子类型(如我之前的回答所示).
但是我们可以将 Array[Int]
转换为 ArraySeq[Int]
,它是 Int => Int
的子类型,因此我们可以进行赋值。
相反的方法不起作用,因为 Int => Int
不是 Array[Int]
也不是 ArraySeq[Int]
请注意,这只是基本子类型,Dog
是 Pet
的子类型,但 Pet
不是 Dog
Which one is the class/trait related to Function[Int, Int]? I have checked the link you mentioned: sealed abstract class ArraySeq[+A] extends AbstractSeq[A] with IndexedSeq[A] with IndexedSeqOps[A, ArraySeq, ArraySeq[A]] with StrictOptimizedSeqOps[A, ArraySeq, ArraySeq[A]] with EvidenceIterableFactoryDefaults[A, ArraySeq, ClassTag] with Serializable
那些是类 / traits ArraySeq
直接扩展的,在Scaladoc link中有一个按钮可以看到所有的supper类型您会看到 (Int) => A
编辑
The last question is which super type does the (Int) => A come from? There are too many types ArraySeq extended.
您需要遍历层级:
- immutable.ArraySeq 扩展 immutable.AbstractSeq
- immutable.AbstractSeq 扩展 immutable.Seq
- immutable.Seq 扩展 collection.Seq
- collection.Seq 扩展 PartialFunction[Int, A]
- PartialFunction[Int, A] extends Function1[Int, A]