开发者

Manipulating tuples

开发者 https://www.devze.com 2023-03-29 16:36 出处:网络
Is there a way to manipulate multiple values of a tuple without using a temporary variable and starting a new statement?

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
0

精彩评论

暂无评论...
验证码 换一张
取 消