tags:

views:

332

answers:

7

I'm new to scala, and what I'm learning is tuple.

I can define a tuple as following, and get the items:

val tuple = ("Mike", 40, "New York")
println("Name: " + tuple._1)
println("Age: " + tuple._2)
println("City: " + tuple._3)

My question is:

  1. How to get the length of a tuple?
  2. Is tuple mutable? Can I modify its items?
  3. Is there any other useful operation we can do on a tuple?

Thanks in advance!

+4  A: 
  1. You know the size of a tuple, it's part of it's type. For example if you define a function def f(tup: (Int, Int)), you know the length of tup is 2 because values of type (Int, Int) (aka Tuple2[Int, Int]) always have a length of 2.
  2. No.
  3. Not really. Tuples are useful for storing a fixed amount of items of possibly different types and passing them around, putting them into data structures etc. There's really not much you can do with them, other than creating tuples, and getting stuff out of tuples.
sepp2k
+15  A: 

1] tuple.productArity

2] No.

3] Some interesting operations you can perform on tuples: (a short REPL session)

scala> val x = (3, "hello")
x: (Int, java.lang.String) = (3,hello)

scala> x.swap
res0: (java.lang.String, Int) = (hello,3)

scala> x.toString
res1: java.lang.String = (3,hello)

scala> val y = (3, "hello")
y: (Int, java.lang.String) = (3,hello)

scala> x == y
res2: Boolean = true

scala> x.productPrefix
res3: java.lang.String = Tuple2

scala> val xi = x.productIterator
xi: Iterator[Any] = non-empty iterator

scala> while(xi.hasNext) println(xi.next)
3
hello

See scaladocs of Tuple2, Tuple3 etc for more.

missingfaktor
@Rahuλ G, thank you again!
Freewind
@Freewind, Welcome!
missingfaktor
+4  A: 

Tuples are immutable, but, like all cases classes, they have a copy method that can be used to create a new Tuple with a few changed elements:

scala> (1, false, "two")
res0: (Int, Boolean, java.lang.String) = (1,false,two)

scala> res0.copy(_2 = true)
res1: (Int, Boolean, java.lang.String) = (1,true,two)

scala> res1.copy(_1 = 1f)
res2: (Float, Boolean, java.lang.String) = (1.0,true,two)
retronym
+9  A: 

One thing that you can also do with a tuple is to extract the content using the match expression:

def tupleview( tup: Any ){
  tup match {
    case (a: String, b: String) =>
      println("A pair  of strings: "+a + " "+ b)
    case (a: Int, b: Int, c: Int) =>
      println("A triplet of ints: "+a + " "+ b + " " +c)
    case _ => println("Unknown")
  }
}

tupleview( ("Hello", "Freewind"))
tupleview( (1,2,3))

Gives:

A pair  of strings: Hello Freewind
A triplet of ints: 1 2 3
olle kullberg
@olle, thanks for this nice example
Freewind
+2  A: 

Another nice trick ad question 3) (as 1 and 2 are already answered by others)

val tuple = ("Mike", 40, "New York")
tuple match  {
  case (name, age, city) =>{
    println("Name: " + name)
    println("Age: " + age)
    println("City: " + city)
  }
}

Edit: in fact it's rather a feature of pattern matching and case classes, a tuple is just a simple example of a case class...

Sandor Murakozi
@Sandor, thank you, helpful
Freewind
+2  A: 

1 and 2 have already been answered.

A very useful thing that you can use tuples for is to return more than one value from a method or function. Simple example:

// Get the min and max of two integers
def minmax(a: Int, b: Int): (Int, Int) = if (a < b) (a, b) else (b, a)

// Call it and assign the result to two variables like this:
val (x, y) = minmax(10, 3)     // x = 3, y = 10
Jesper
+2  A: 

Concerning question 3:

A useful thing you can do with Tuples is to store parameter lists for functions:

def f(i:Int, s:String, c:Char) = s * i + c
List((3, "cha", '!'), (2, "bora", '.')).foreach(t => println((f _).tupled(t)))
//--> chachacha!
//--> borabora.

[Edit] As Randall remarks, you'd better use something like this in "real life":

def f(i:Int, s:String, c:Char) = s * i + c
val g = (f _).tupled
List((3, "cha", '!'), (2, "bora", '.')).foreach(t => println(g(t)))

In order to extract the values from tuples in the middle of a "collection transformation chain" you can write:

val words = List((3, "cha"),(2, "bora")).map{ case(i,s) => s * i }

Note the curly braces around the case, parentheses won't work.

Landei
Note that in this construction, you're going to synthesize the tupled versions of the function that was itself lifted from method `f` *on each iteration of the `foreach`*.
Randall Schulz