agrinh
agrinh

Reputation: 1905

Implicit class applicable to all Traversable subclasses including Array

I've run into a problem trying to create an implicit class applicable to all Traversable subclasses including Array. I tried the following simple example in both Scala 2.11.1 and 2.10.4:

implicit class PrintMe[T](a: Traversable[T]) {
  def printme = for (b <- a) print(b)
}

As far as I understand this should allow for an implicit conversion to PrintMe so that printme can be called on any Traversable, including List and Array. E.g:

scala> List(1,2,3).printme
123
// Great, works as I expected!

scala> Array(1,2,3).printme
<console>:23: error: value printme is not a member of Array[Int]
              Array(1,2,3).printme
// Seems like for an Array it doesn't!

scala> new PrintMe(Array(1,2,3)).printme
123
// Yet explicitly building a PrintMe from an Array works 

What's going on here? Why does the implicit conversion work for a List and not an Array?

I understand there has been some trickery adapting java Arrays but looking at the picture below from http://docs.scala-lang.org/overviews/collections/overview.html it certainly seems like Array is meant to behave like a subclass of Traversable.

scala.collection.immutable

Upvotes: 2

Views: 419

Answers (1)

dhg
dhg

Reputation: 52691

It's as @goral said: only one implicit conversion can happen at a time.

So you can pass an Array where a Traversable is expected since Array will become a WrappedArray:

def printme[T](a: Traversable[T]) { for (b <- a) print(b) }
printme(Vector(1,2,3))
printme(Array(1,2,3))

Or you can use your implicit on a manually-wrapped Array:

val wa = scala.collection.mutable.WrappedArray.make(Array(1, 2, 3))
wa.printme

But you can't have both at the same time.

Upvotes: 5

Related Questions