Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Manipulating tuples

Tags:

tuples

scala

Is there a way to manipulate multiple values of a tuple without using a temporary variable and starting a new statement?

Say I have a method that returns a tuple and I want to do something with those values inline.

e.g. if I want to split a string at a certain point and reverse the pieces

def backToFront(s: String, n:Int) = s.splitAt(n)...

I can do

val (a, b) = s.splitAt(n)
b + a 

(requires temporary variables and new statement) or

List(s.splitAt(n)).map(i => i._2 + i._1).head

(works, but seems a bit dirty, creating a single element List just for this) or

s.splitAt(n).swap.productIterator.mkString

(works for this particular example, but only because there happens to be a swap method that does what I want, so it's not very general).

The zipped method on tuples seems just to be for tuples of Lists.

As another example, how could you turn the tuple ('a, 'b, 'c) into ('b, 'a, 'c) in one statement?

like image 280
Luigi Plinge Avatar asked Aug 20 '11 05:08

Luigi Plinge


2 Answers

Tuples are just convenient return type, and it is not assumed that you will make complicated manipulations with it. Also there was similar discussion on scala forums.

About the last example, couldn't find anything better than pattern-matching.

('a, 'b, 'c) match { case (a, b, c) => (b, a ,c) }
like image 120
4e6 Avatar answered Sep 29 '22 12:09

4e6


Unfortunately, the built-in methods on tuples are pretty limited.

Maybe you want something like these in your personal library,

def fold2[A, B, C](x: (A, B))(f: (A, B) => C): C = f(x._1, x._2)
def fold3[A, B, C, D](x: (A, B, C))(f: (A, B, C) => D): D = f(x._1, x._2, x._3)

With the appropriate implicit conversions, you could do,

scala> "hello world".splitAt(5).swap.fold(_ + _)
res1: java.lang.String = " worldhello"

scala> (1, 2, 3).fold((a, b, c) => (b, c, a))
res2: (Int, Int, Int) = (2,3,1)

An alternative to the last expression would be the "pipe" operator |> (get it from Scalaz or here),

scala> ('a, 'b, 'c) |> (t => (t._2, t._3, t._1))
res3: (Symbol, Symbol, Symbol) = ('b,'c,'a)

This would be nice, if not for the required annotations,

scala> ("hello ", "world") |> (((_: String) + (_: String)).tupled)
res4: java.lang.String = hello world
like image 33
Kipton Barros Avatar answered Sep 29 '22 12:09

Kipton Barros