List and Tuples in Scala

前端 未结 5 1941
温柔的废话
温柔的废话 2021-01-27 08:33

From the book \'Programming in Scala\' by Martin Odersky:

Another useful container object is the tuple. Like lists, tuples are immutable, but unlike lis

5条回答
  •  刺人心
    刺人心 (楼主)
    2021-01-27 08:58

    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
    

提交回复
热议问题