0

Given:

scala> val ss = "hello_world".split("_")
ss: Array[String] = Array(hello, world)

How to turn ss into a tuple (hello, world) with a function of Array (on ss)? I'm thinking about a function so the above snippet would end up as "hello_world".split("_").to[Tuple2] or alike.

Is it possible using Scala 2.11.6 API only?

Jacek Laskowski
  • 72,696
  • 27
  • 242
  • 420
  • Not really a dup I think – yǝsʞǝla May 10 '15 at 13:20
  • 3
    Why do you want to do this? If you don't know how many elements will result from the split, you can't say anything about the type of the resulting tuple. So then what will you do with it? If you're looking for heterogeneous lists, see Shapeless's HList https://github.com/milessabin/shapeless – The Archetypal Paul May 10 '15 at 14:41
  • There are some ways for converting a list to a tuple at http://stackoverflow.com/questions/11305290/is-there-way-to-create-tuple-from-listwithout-codegeneration. They could be used to convert an array to a tuple by starting with array.toList. –  May 11 '15 at 08:19

3 Answers3

0

The shortest I could come up with:

scala> "hello_world" split("_") match { case Array(f, s) => (f, s) }
res0: (String, String) = (hello,world)

Of course it will throw for other non Tuple2 cases. You can have this to avoid exceptons:

scala> "hello_world" split("_") match { case Array(f, s) => Some(f, s); case _ => None } 
res1: Option[(String, String)] = Some((hello,world))

Or with implicits:

scala> implicit class ArrayTupple[T](val a: Array[T]) { def pair = a match { case Array(f, s) => (f, s) } }
defined class ArrayTupple

scala> val ss = "hello_world".split("_")
ss: Array[String] = Array(hello, world)

scala> ss.pair
res0: (String, String) = (hello,world)

I'm still not very happy with the solution. Seems like you have to either write out all possible cases up to Tuple22 to make more generic method like to[Tuple22] or maybe use macros.

yǝsʞǝla
  • 16,272
  • 2
  • 44
  • 65
0

Unfortunatelly there's no function, that can convert Array of N elements (of course N <= 22) to TupleN. There is a proposed change to Scala API[1] to add :+ and +: methods to a tuple, but it has a low priority. What people do in their projects is basically summed up in an SO question [2].

If you do what they propose, and create classes from TupleOps2 to Tuple22` it still wouldn't be possible. Look at the code below:

def array2Tuple[T](array: Array[T]): TupleN = {
  if(array.length == 2)
    (array(0), array(1))
  else
    array(0) +: array2Tuple(array.drop(1))
}

It is still not possible, to deduce N in TupleN return type. The problem here is of course with the size of the array vs. size of Tuple. Size of array is contained inside the object, while size of Tuple is contained in a type name.

References:

Community
  • 1
  • 1
Bartek Andrzejczak
  • 1,292
  • 2
  • 14
  • 27
0

I don't think you can do better than

"size_known".split("_") match { case Array(a, b) => (a, b) }

or

Some("size_is_unknown".split("_")) collect { case Array(a, b) => (a, b) }

without reinventing some features of Shapeless, that makes it easy

Community
  • 1
  • 1
Przemek Pokrywka
  • 2,219
  • 17
  • 23