Cotton Seed
Cotton Seed

Reputation: 363

Type parameterization and strange cast exception

I have the following code which splits an array into an array of arrays before any element that satisfies the predicate p. It type checks:

def splitBefore[T](a: Array[T], p: (T) => Boolean)
      (implicit tct: ClassTag[T]): Array[Array[T]] =
  a.foldLeft(Array[Array[T]](Array.empty[T])) {
(acc: Array[Array[T]], s: T) => if (p(s))
  acc :+ Array(s)
else
  acc.init :+ (acc.last :+ s)
}

It works fine when I call it with non-empty a:

scala> splitBefore(Array("a", "BC", "d"), (s: String) => s.size > 1)
res1: Array[Array[String]] = Array(Array(a), Array(BC, d))

But when I call it with an empty array, I get a ClassCastException:

scala> splitBefore(Array.empty[String], (s: String) => s.size > 1)
java.lang.ClassCastException: [Ljava.lang.Object; cannot be cast to [[Ljava.lang.String;
  ... 33 elided

When I hand-inline the call so there is no type parameterization, it works fine:

scala> Array().foldLeft(Array(Array.empty[String])) {
     |   (acc: Array[Array[String]], s: String) => if (s.size > 1)
     |     acc :+ Array(s)
     |   else
     |     acc.init :+ (acc.last :+ s)
     | }
res1: Array[Array[String]] = Array(Array())

Any idea what's going on here? I'm using Scala 2.11.7.

Upvotes: 3

Views: 72

Answers (1)

Wojciech Ptak
Wojciech Ptak

Reputation: 683

Looks like instantiating a nested array causes a bug - it crashes even on such a small example:

def instantiate[A](ununsed_arg: Array[T])(implicit tag: ClassTag[A]) =
  Array[Array[A]](Array.empty[A])

As a quick workaround, you might use an ArrayBuilder to create an array:

def instantiate[T](a: Array[T])(implicit ctc: ClassTag[T]) = {
  val builder = ArrayBuilder.make[Array[T]]
  builder += Array.empty[T]
  builder.result
}

Also please note that your snippet directly appends elements to an array, which is a bad idea because it has to create a new array with one more slot and copy an element. Looks like you should either use an ArrayBuilder or ArrayBuffer to do the processing or build your new data structure out of Lists and convert them to Arrays at the end.

Upvotes: 2

Related Questions