1

I am trying to copy an array of generic type using maps.

class MaObj[T](val arr : Array[T])(implicit ordering : Ordering[T]) {

  val internalCopy : Array[T] = arr.map(e => e) //This line

But I run it gives an error saying

found   : scala.collection.mutable.ArraySeq[T]
 required: Array[T]
 Note: implicit value comparison is not applicable here because it comes after the application point and it lacks an explicit result type
val internalCopy : Array[T] = arr.map(e => e)

I am not able to make sense of this.

Ashwin
  • 12,691
  • 31
  • 118
  • 190
  • The problem you are referring to is well explained [here](https://stackoverflow.com/questions/12837799/scala-array-map-returns-arrayseq). – Markus Appel Nov 15 '18 at 10:16
  • It's not really explained there. There is an answer showing a workaround, but no explanation of _why_ this behavior exists. – Dima Nov 15 '18 at 12:26

2 Answers2

1

Instead of using your approach of .map combined with the identity, you can easily copy the Array using .clone.

Your code would look like this:

class MaObj[T](val arr : Array[T])(implicit ordering : Ordering[T]) {

  val internalCopy: Array[T] = arr.clone

}

Try it out!

I hope this helps.

Markus Appel
  • 3,138
  • 1
  • 17
  • 46
1

So, the problem is that .map returns ArraySeq rather than Array when there is no type information for the array elements at compile time. This is because you need to have the actual class for the elements: Array.newInstance(clazz, numElements). When you specify the element type as just T, that's not available, so when you do .map it switches the container type to ArraySeq to work around that limitation.

One way around that is pass the class information down to your class:

class MaObj[T : ClassTag : Ordering](val arr : Array[T])

(this is equivalent to class MaObj[T](val arr: Array[T])(implicit ev1: ClassTag[T], ev2: Ordering[T])

This passes an implicit parameter to the class, that lets it resolve the element type at run time.

Another way, if you really just want to copy the array without transforming its elements, you can just use .clone, as the other answer suggests. It is a lot more efficient too.

Or just use IndexedSeq instead of Array to begin with, it is better anyway.

Dima
  • 39,570
  • 6
  • 44
  • 70