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)
i开发者_如何学编程n one statement?
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) }
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
How about this?
s.splitAt(n) |> Function.tupled(_ + _)
[ Edit: Just noticed your arguments to function are reversed. In that case, you will have to give up placeholder syntax and instead go for: s.splitAt(n) |> Function.tupled((a, b) => b + a)
]
For your last example, can't think of anything better than a pattern match (as shown by @4e6.)
With the current development version of shapeless, you can achieve this without unpacking the tuple:
import shapeless.syntax.std.tuple._
val s = "abcdefgh"
val n = 3
s.splitAt(n).rotateRight[shapeless.Nat._1].mkString("", "", "") // "defghabc"
I think you shouldn't have to wait too long (matter of days I'd say) before the syntax of the methods of the last line get cleaned, and you can simply write
s.splitAt(n).rotateRight(1).mkString
精彩评论