It is a question followed by this.
Now we have proved that Array[Int]
could be implicitly converted into Int => Int
, but where is the place that happens?
Obviously, Int => Int
is a Function:
scala> var fun = (i: Int) => Array(1,2,3)(i)
fun: Int => Int = <function1>
And Array[Int]
is a class:
scala> var arr = Array(1,2,3)
arr: Array[Int] = Array(1, 2, 3)
But arr
can be assigned to fun
:
scala> fun = arr
fun: Int => Int = WrappedArray(1, 2, 3)
Conversely, it will not work:
scala> arr = fun
<console>:34: error: type mismatch;
found : Int => Int
required: Array[Int]
arr = fun
^
Now, Where is the place that implicit conversion happens?
CodePudding user response:
When you assign Array(1)
to a val
of type Int => Int
, the implicit conversion scala.LowPriorityImplicits#wrapIntArray
is called.
It wraps the Array
into ArraySeq
and the later implements Function1
or Int => Int
CodePudding user response:
Since you have WrappedArray
I'm guessing you have Scala 2.12 or earlier - Scala 2.13 has ArrayOps
.
There is an implicit conversion (actually a whole family o conversions) from Array
to WrappedArray
. So you have an implicit conversion from Array[T]
to WrappedArray[T]
.
Now, WrappedArray
implements all sorts of Scala's collection traits. One of them is Seq
implementing PartialFunction
(which in turn extends Function
). That means that all of collections in Scala are functions from some key (Int
in case of sequences, possibly something else in case of Map
s). This includes WrappedArray
.
So your conversion to WrappedArray
automatically turns an Array[T]
into a (subtype of a) function Int => T
.
As a matter of the fact, this is a reason why you should avoid putting any collection (or things implicitly convertible to collections like Array
before 2.13) into implicit scope: a collection in implicit scope automatically becomes implicit conversion itself. This problem was solved only in Scala 3 where implicit conversions became a separate subtype of Function
interface.
CodePudding user response:
but where is the place that happens?
Implicit conversions happen when necessary, in this case in the assignment itself.
Look at my reify
block in my other answer:
val foo: Function1[Int, Int] = Predef.wrapIntArray(Array.apply(1, 2, 3));
That is the conversion right there, calling the method: wrapIntArray
in the Predef
object.
Obviously, Int => Int is a Function:
And Array[Int] is a class:
But arr can be assigned to fun:
Conversely, it will not work:
It seems you don't know / understand that in Scala functions
are also objects
(almost everything in Scala is an object
, anything that is a value will be an object
).
So we can't directly assign an Array[Int]
to a value that should be an Int => Int
; because Array[Int]
is not a subtype of Int => Int
(as shown in my previous answer).
But we can convert an Array[Int]
into an ArraySeq[Int]
which is a subtype of an Int => Int
and thus we can do the assignment.
The opposite won't work because an Int => Int
is not an Array[Int]
nor a ArraySeq[Int]
Note this is just basic subtyping, a Dog
is a subtype of Pet
but a Pet
is NOT a subtype of 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
Those are the classes / traits ArraySeq
directly extends, in the Scaladoc link there is a button to see all supper types ad in those you will see (Int) => A
Edit
The last question is which super type does the (Int) => A come from? There are too many types ArraySeq extended.
You need to traverse the hierarchy:
- immutable.ArraySeq extends immutable.AbstractSeq
- immutable.AbstractSeq extends immutable.Seq
- immutable.Seq extends collection.Seq
- collection.Seq extends PartialFunction[Int, A]
- PartialFunction[Int, A] extends Function1[Int, A]