为什么Scala的元组语法如此不寻常?

在math和计算机科学中,元组是有序的元素列表。 在集合论中,(有序的)n元组是n个元素的序列(或有序列表),其中n是正整数。

因此,例如,在Python中,元组的第二项可以通过t[1]访问。

在Scala中,访问只能通过奇怪的名字t._2

所以问题是,为什么我不能以Sequence或List的forms访问元组中的数据? 有没有什么想法,还是没有检查?

Scala知道元组的元组,因此能够提供诸如_1_2等的访问器,并且如果在对上select_3 ,则会产生编译时错误。 而且,这些字段的types正是用于Tuple参数的types(例如Tuple3[Int, Double, Float]上的_3将返回一个Float )。

如果你想访问第n个元素,你可以写tuple.productElement(n) ,但是这个返回types只能是Any ,所以你会丢失types信息。

我相信以下“Scala编程:全面的分步指南”摘录(Martin Odersky,Lex Spoon和Bill Venners)直接解决了以下两个问题:

访问元组的元素

你可能想知道为什么你不能像列表元素一样访问元组的元素,例如,“pair(0)”。 原因是列表的apply方法总是返回相同的types,但是元组中的每个元素可能是不同的types:_1可以有一个结果types,_2可以有另一个types,依此类推。 这些_N数字是基于一个的,而不是基于零的,因为从1开始是其他语言使用静态types元组(例如Haskell和ML)设置的传统。

就语言语法而言,除了expression式'(' a1, ..., an ')'被编译器视为scala的别名之外,Scala元组得到了很less的优待.Tuplen( a1,… ,一 )类实例化。 否则,元组的行为与其他Scala对象相同,实际上它们是以Scala编写的,范围从Tuple2到Tuple22 。 Tuple2和Tuple3分别在Pair和Triple的别名下也是已知的:

  val a = Pair (1,"two") // same as Tuple2 (1,"two") or (1,"two") val b = Triple (1,"two",3.0) // same as Tuple3 (1,"two",3.0) or (1,"two",3.0) 

ListSeq或者任何集合和元组之间的一个很大的区别是,在元组中,每个元素都有它自己的types,在List中,所有元素都具有相同的types。

因此,在Scala中你会发现类Tuple2[T1, T2]或者Tuple3[T1, T2, T3] ,所以每个元素都有types参数。 集合只接受1个types参数: List[T] 。 语法like ("Test", 123, new Date)只是Tuple3[String, Int, Date]语法糖。 而_1_2等只是返回对应元素的元组的字段。

你可以很容易地达到目的:

 import shapeless.syntax.std.tuple._ val t = ("a", 2, true, 0.0) val s = t(0) // String at compile time val i = t(1) // Int at compile time // etc 

标准集合的很多方法也可以用于元组( headtailinitlast++:::用于连接, +::+用于添加元素, takedropreversezipunziplengthtoListtoArrayto[Collection] ,…)

对于正常的索引访问,可以使用任何expression式,并且在编译时检查索引expression式的结果是否保证在范围内会花费一些认真的努力。 使其成为一个属性,并且(1, 2)._3的编译时错误在“免费”之后。 比如只允许在元组访问内部的整数常量是一个非常特殊的情况(丑陋和不必要的,有些人会说是荒谬的),再一些工作要在编译器中实现。

例如,Python可以避免这种情况,因为如果索引在范围内,它不会(不能)检查(在编译时,就是这样)。

我认为这是为了检查types。 正如delnan所说,如果你有一个元组t和一个索引e (一个任意expression式), t(e)会给编译器提供关于哪个元素被访问的信息(或者即使它是这个大小的元组的有效元素)。 当通过字段名称访问元素( _2是一个有效的标识符,它不是特殊的语法)时,编译器知道你正在访问哪个字段以及它有什么types。 像Python这样的语言并不是真的有types,所以这对于他们来说是不必要的。

除了Jean-Philippe Pellet已经提到的好处之外,这个表示法在math中也很常见(见http://en.wikipedia.org/wiki/Tuple )。 如果想要引用元组的元素,很多讲师会将索引附加到元组variables上。 用“写索引n ”(指元组的第n个元素)的通用(LaTeX)符号是_n 。 所以我觉得它非常直观。