Home > Net >  Where is the place that 'Array[Int]' is implicitly converted to 'Int => Int'
Where is the place that 'Array[Int]' is implicitly converted to 'Int => Int'

Time:11-19

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 Maps). 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:

  1. immutable.ArraySeq extends immutable.AbstractSeq
  2. immutable.AbstractSeq extends immutable.Seq
  3. immutable.Seq extends collection.Seq
  4. collection.Seq extends PartialFunction[Int, A]
  5. PartialFunction[Int, A] extends Function1[Int, A]
  • Related