Scala中的列表和元组

Man*_*oid 0 scala tuples list

从马丁·奥德斯基(Martin Odersky)的《斯卡拉编程》一书中:

另一个有用的容器对象是元组。像列表一样,元组是不可变的,但是与列表不同,元组可以包含不同类型的元素。

但是我可以有:

val oneTwoThreee = List(1, 2, "Third Element") //same as:List.apply(1,2,3)
for (i <- 0 to 2) {
  println(oneTwoThreee.apply((i)))
}
Run Code Online (Sandbox Code Playgroud)

其输出为:

1 
2
Third Element
Run Code Online (Sandbox Code Playgroud)

因此,Scala中的List可以具有不同类型的元素。

从同一本书:

您可能想知道为什么您无法访问元组的元素(如列表元素),例如,使用“ pair(0)”。原因是列表的apply方法始终返回相同的类型,但是元组的每个元素可能是不同的类型:

但是如上面的代码所示,List.apply()可以返回不同的类型。

我在这里是否缺少有关Scala中的List和Tuple的信息?

Yuv*_*kov 5

我在这里是否缺少有关Scala中的List和Tuple的信息?

我认为Odersky试图说明的要点是,每个元组元素可以包含自己的单独类型,从而可以使用多种不同类型。东西,一个List如果你想要一个不能这样做,因为名单是均匀的,意思是List[Int],该列表中的所有元素必须是Int值。

如果查看创建的列表的类型,您会看到编译器会推断出List[Any],这是所有Scala类型的通用超类型。这意味着,如果您要对列表中的元素之一进行具体处理,即head元素是type Int,则不能,因为编译器知道的所有元素都是type Any,而您我将需要一些如何提取底层“具体”类型的方法:

scala> val oneTwoThreee = List(1,2,"Third Element")
oneTwoThreee: List[Any] = List(1, 2, Third Element)
Run Code Online (Sandbox Code Playgroud)

使用时Tuple3[Int, Int, String],实际上会“保留”具体类型:

scala> val tup = (1, 2, "Third Element")
tup: (Int, Int, String) = (1,2,Third Element)
Run Code Online (Sandbox Code Playgroud)

现在,如果我们要提取一个Int值并将它们增加1,我们可以:

scala> tup.copy(tup._1 + 1)
res1: (Int, Int, String) = (2,2,Third Element)
Run Code Online (Sandbox Code Playgroud)

如果我们尝试对进行相同操作List[Any],则编译器将正确地抱怨:

scala> oneTwoThreee.head + 1
<console>:13: error: type mismatch;
 found   : Int(1)
 required: String
       oneTwoThreee.head + 1
                           ^
Run Code Online (Sandbox Code Playgroud)

该错误在某种程度上具有误导性,但这是由于事实head实际上是type引起的Any

使用shapeless及其HList数据类型使用异构列表的可能性更高 :

import shapeless._

object Tests {
  def main(args: Array[String]): Unit = {
    val hList = 1 :: 2 :: "Third" :: HNil

    println(hList.head + 1)
  }
}
Run Code Online (Sandbox Code Playgroud)

产生:

2
Run Code Online (Sandbox Code Playgroud)