From the book \'Programming in Scala\' by Martin Odersky:
Another useful container object is the tuple. Like lists, tuples are immutable, but unlike lis
Am I missing something here regarding List and Tuples in Scala?
I think the main point Odersky is trying to show is that each tuple element can contain its own individual type, which allows using multiple different types. Something that a List can't do because a list is homogeneous, meaning if you want a List[Int], all elements of that list must be Int values.
If you look at the type of the list you created, you'll see that the compiler infers List[Any], which is the common supertype of all Scala types. This means that if you want to do something concrete with the one of the elements in the list, i.e. it's head element which is of type Int, you can't because all the compiler knows about that element is that its of type Any, and you'll need to some how extract the underlying "concrete" type:
scala> val oneTwoThreee = List(1,2,"Third Element")
oneTwoThreee: List[Any] = List(1, 2, Third Element)
While using a Tuple3[Int, Int, String], actually "keeps" the concrete types:
scala> val tup = (1, 2, "Third Element")
tup: (Int, Int, String) = (1,2,Third Element)
Now if we want to extract one of the Int values and increment them by 1, we can:
scala> tup.copy(tup._1 + 1)
res1: (Int, Int, String) = (2,2,Third Element)
If we tried doing the same with a List[Any], the compiler would rightfully complain:
scala> oneTwoThreee.head + 1
:13: error: type mismatch;
found : Int(1)
required: String
oneTwoThreee.head + 1
^
The error is somewhat misleading, but this happens due to the fact head is actually of type Any.
There is a more advanced possibility of using heterogeneous lists using shapeless and it's HList data type:
import shapeless._
object Tests {
def main(args: Array[String]): Unit = {
val hList = 1 :: 2 :: "Third" :: HNil
println(hList.head + 1)
}
}
Which yields:
2