3

I did experiment on CanBuildFrom trait on Scala, it looks fine when I try to convert Array type to Seq type automatically, I think the reason is that we have CanBuildFrom[Array, T, Seq[T]] in the scope. However, if I try to convert Array to Set, it is not working. Further, Converting Seq to Set is not working as well. I just wonder should I define implicit into same type CanBuildFrom companion object to implement conversion ?. If it is, why scala doesnt provide it by default, is reason Set is a function ?

Here is the code which for Array to Seq

def transform[U[_]](col: Array[String])(implicit cbf: CanBuildFrom[Array[String], String, U[String]]): U[String] = {
    val builder = cbf()

    for (ele <- col) builder += ele

    builder.result()
  }

CanBuildFromSpec.transform[Seq](Array("123", "3"))

If I want to convert to Array to Set or List, it is not working

CanBuildFromSpec.transform[List](Array("123", "3")) //compilation error, cannot construct
CanBuildFromSpec.transform[Set](Array("123", "3")) //compilation error, cannot construct
om-nom-nom
  • 62,329
  • 13
  • 183
  • 228
Xiaohe Dong
  • 4,953
  • 6
  • 24
  • 53
  • 1
    You can supply `collection.breakOut` as the `CanBuildFrom` to your `transform` to allow you to build any collection (any that can holds strings at least). Or you can declare an implicit `CanBuildFrom` of the needed type. – wingedsubmariner May 30 '14 at 05:11

1 Answers1

3

There is no need to reinvent a wheel - Scala collections have to[C[_]] method which allows conversion as you want it:

scala> List(1, 2, 3).to[Vector]
res0: Vector[Int] = Vector(1, 2, 3)

scala> Array(1, 2, 3).to[Seq]
res1: Seq[Int] = Vector(1, 2, 3)

scala> Seq(1, 2, 3).to[Set]
res2: Set[Int] = Set(1, 2, 3)

BTW, CanBuildFrom was introduced not for easy convertibility. It was needed in order for operations like map() or filter() to preserve original collection types.

Also Array is converted to Seq automatically not because of CanBuildFrom (that would imply that array contents are copied into the new sequence, which can be pretty inefficient), but because there is an implicit conversion from arrays to their wrappers providing Seq interface.

Vladimir Matveev
  • 120,085
  • 34
  • 287
  • 296
  • 2
    Thanks for your comment, I know "to" can do stuff, but CanBuildForm is very useful for generic programming on Collection. For instance, if I want to apply for calculation logic on the collection and I dont want to duplicate function for different collection, CanBuildForm is a good choice. Thus, in this case, "asInstanceof" or "to" are not what I am looking for. – Xiaohe Dong May 30 '14 at 06:35