Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/list/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Scala中的列表和元组_Scala_List_Tuples - Fatal编程技术网

Scala中的列表和元组

Scala中的列表和元组,scala,list,tuples,Scala,List,Tuples,来自Martin Odersky的《Scala编程》一书: 另一个有用的容器对象是tuple。像列表一样,元组是不可变的, 但与列表不同,元组可以包含不同类型的元素 但我可以: val oneTwoThreee = List(1, 2, "Third Element") //same as:List.apply(1,2,3) for (i <- 0 to 2) { println(oneTwoThreee.apply((i))) } val oneTwoThreee = List(1

来自Martin Odersky的《Scala编程》一书:

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

但我可以:

val oneTwoThreee = List(1, 2, "Third Element") //same as:List.apply(1,2,3)
for (i <- 0 to 2) {
  println(oneTwoThreee.apply((i)))
}
val oneTwoThreee = List(1, 2, "Third Element") //same as:List.apply(1,2,3)
for (i <- 0 to 2) {
  println(oneTwoThreee.apply((i)))
}
所以Scala中的列表可以有不同类型的元素

来自同一本书:

您可能想知道为什么不能访问元组的元素 与列表中的元素类似,例如,带有“pair(0)”。原因 列表的apply方法总是返回相同的类型,但每个 元组的元素可以是不同的类型:

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

关于Scala中的列表和元组,我遗漏了什么吗

关于Scala中的列表和元组,我遗漏了什么吗

我认为Odersky试图说明的要点是,每个元组元素都可以包含自己的类型,这允许使用多种不同的类型。由于列表是同质的,
列表
不能做的事情,这意味着如果您想要一个
列表[Int]
,该列表的所有元素都必须是
Int

如果查看您创建的列表的类型,您将看到编译器推断出
list[Any]
,这是所有Scala类型的公共超类型。这意味着,如果您想对列表中的一个元素做一些具体的事情,即它的head元素的类型是
Int
,您不能,因为编译器所知道的关于该元素的所有信息都是它的类型是
Any
,您需要了解如何提取底层的“具体”类型:

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

scala> val tup = (1, 2, "Third Element")
tup: (Int, Int, String) = (1,2,Third Element)
现在,如果我们想提取一个
Int
值并将它们增加1,我们可以:

scala> tup.copy(tup._1 + 1)
res1: (Int, Int, String) = (2,2,Third Element)
如果我们尝试对
列表[Any]
执行同样的操作,编译器会理所当然地抱怨:

scala> oneTwoThreee.head + 1
<console>:13: error: type mismatch;
 found   : Int(1)
 required: String
       oneTwoThreee.head + 1
                           ^
这将产生:

2
简而言之:

  • 在列表中,所有元素都属于同一类型(即使是包含所有元素的任何类型)
  • 在元组中,每个元素都有自己的类型
对于列表,不能要求第一个元素必须是字符串,第二个元素必须是数字。对于元组,您可以,编译器将静态地检查它

接下来,您可以拥有任意长度的列表,因为所有元素都是相似的,但元组只能具有固定长度,每个元素的类型都单独声明


如果你来自例如C的背景,元组就像结构,列表就像数组。

一个非常简单的例子,展示了其他答案告诉你的内容

val tuplX = (10, "ten")      //tuplX: (Int, String) = (10,ten)
val listX = List(10, "ten")  //listX: List[Any] = List(10, ten)

tuplX._1 - 6     //res0: Int = 4
tuplX._2.length  //res1: Int = 3

listX(0) - 6     //Error: value - is not a member of Any
listX(1).length  //Error: value length is not a member of Any
但我可以:

val oneTwoThreee = List(1, 2, "Third Element") //same as:List.apply(1,2,3)
for (i <- 0 to 2) {
  println(oneTwoThreee.apply((i)))
}
val oneTwoThreee = List(1, 2, "Third Element") //same as:List.apply(1,2,3)
for (i <- 0 to 2) {
  println(oneTwoThreee.apply((i)))
}
所以Scala中的列表可以有不同类型的元素

不,不能。列表的类型是
list[Any]
,因此所有元素的类型都相同:
Any

如果在Scala REPL中键入代码,它将在每一步告诉您代码的类型:

scala> val oneTwoThreee = List(1, 2, "Third Element") //same as:List.apply(1,2,3)
oneTwoThreee: List[Any] = List(1, 2, Third Element)
              ↑↑↑↑↑↑↑↑↑
oneTwoThreee(0)
//=> res: Any = 1
//        ↑↑↑

oneTwoThreee(1)
//=> res: Any = 2
//        ↑↑↑

oneTwoThreee(2)
//=> res: Any = Third Element
//        ↑↑↑
您也可以向Scala REPL询问类型:

scala> :type oneTwoThreee
List[Any]
是一种非常通用的类型,因此非常无用,因为它没有任何“有趣”的方法。事实上,使用
Any
:,您所做的几乎是唯一可以做的事情。这就是为什么你没有注意到这个问题,你碰巧选了唯一有效的东西

尝试将列表的第一个和第二个元素相乘:

oneTwoThreee(0) * oneTwoThreee(1)
// error: value * is not a member of Any
       oneTwoThreee(0) * oneTwoThreee(1)
                       ^
您可能想知道为什么不能访问元组的元素 与列表中的元素类似,例如,带有“pair(0)”。原因 列表的apply方法总是返回相同的类型,但每个 元组的元素可以是不同的类型: 但正如上面的代码所示,List.apply()可以返回不同的类型

不,不能。让我们再次询问Scala REPL的类型:

scala> val oneTwoThreee = List(1, 2, "Third Element") //same as:List.apply(1,2,3)
oneTwoThreee: List[Any] = List(1, 2, Third Element)
              ↑↑↑↑↑↑↑↑↑
oneTwoThreee(0)
//=> res: Any = 1
//        ↑↑↑

oneTwoThreee(1)
//=> res: Any = 2
//        ↑↑↑

oneTwoThreee(2)
//=> res: Any = Third Element
//        ↑↑↑

如您所见,类型始终相同:
Any

只是一个注释。如果您得到List元素的类名,Scala就会知道它的类型。可能是类型推断

scala> val l = List(1,2,3,"Adriano Avelar")
val l: List[Any] = List(1, 2, 3, Adriano Avelar)

scala> print(l(3).getClass.getSimpleName)
String

scala> print(l(2).getClass.getSimpleName)
Integer