在数学和计算机科学中,元组是元素的有序列表。在集合论中,(有序的)n元组是n个元素的序列(或有序列表),其中n是正整数。
因此,例如,在Python中,可以通过访问元组的第二项t[1]
。
在Scala中,只能通过奇怪的名称进行访问t._2
。
所以问题是,为什么不能按定义访问序列或列表中的元组数据?是否有某种主意或尚未检查?
Answers:
Scala知道元组的复杂性,因此能够提供诸如_1
,_2
等的访问器,并且,例如,如果_3
在一对上选择,则会产生编译时错误。此外,这些字段的类型正是用作参数的类型Tuple
(例如,_3
在aTuple3[Int, Double, Float]
上将返回a Float
)。
如果要访问第n个元素,则可以编写tuple.productElement(n)
,但是该元素的返回类型只能是Any
,因此您会丢失类型信息。
t[1]
并保留所有类型信息,并简单地让它t[exp]
(在编译时不知道exp的结果)的返回类型为Any
,对吗?因此,似乎语法上的不同更多是为了使程序员明白元组不是列表。
t[exp]
正是t.productElement(exp)`所做的。请注意,在Scala中,方括号仅用于类型参数。
-Xexperimental
在2.10中继中已经可以使用这种方式,但仅适用于案例类,不适用于元组。不知道为什么。
我相信“ Scala编程:全面的循序渐进指南”中的以下摘录(Martin Odersky,Lex Spoon和Bill Venners)直接解决了您的两个问题:
访问元组的元素
您可能想知道为什么您不能访问元组的元素(例如列表对),例如使用“ pair(0)”。原因是列表的apply方法始终返回相同的类型,但是元组的每个元素可能是不同的类型:_1可以具有一个结果类型,_2可以具有另一个结果类型,依此类推。这些_N数字是从1开始的,而不是从0开始的数字,因为其他语言使用静态类型的元组(例如Haskell和ML)以1开头是一个传统。
就语言语法而言,Scala元组几乎没有任何优惠待遇,除了表达式'(' a1, ..., an ')'
被编译器视为scala.Tuplen(a1,...,an)类实例化的别名。否则,元组的行为与任何其他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)
Tuple1
已添加。
之间的一个很大的区别List
,Seq
任何收集和元组或者是在元组的每个元素都有它自己的类型,其中在列表中的所有元素都具有相同的类型。
因此,在Scala中,您会发现类似Tuple2[T1, T2]
或的类Tuple3[T1, T2, T3]
,因此对于每个元素,您也都具有类型参数。集合仅接受一种类型参数:List[T]
。语法("Test", 123, new Date)
只是语法糖Tuple3[String, Int, Date]
。和_1
,_2
等等只是元组上返回相应元素的字段。
您可以轻松地achive与无形的:
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
很多可用于标准的收集方法也可用于元组这样(head
,tail
,init
,last
,++
并:::
进行连结,+:
并:+
添加元素take
,drop
,reverse
,zip
,unzip
,length
,toList
,toArray
,to[Collection]
,...)
使用普通索引访问,可以使用任何表达式,并且如果保证索引表达式的结果在范围内,则将花费大量精力检查编译时。使其成为一个属性,并为(1, 2)._3
“免费”提供一个编译时错误。诸如在元组的项访问中仅允许整数常量之类的事情将是一个非常特殊的情况(丑陋且不必要,有些人说这很荒谬),并且还有一些工作要在编译器中实现。
例如,Python可以避免这种情况,因为它不会(无法)在编译时检查索引是否在范围内。
除了让·菲利普·佩莱特(Jean-Philippe Pellet)已经提到的好处外,这种表示法在数学中也很常见(请参见http://en.wikipedia.org/wiki/Tuple)。如果他们想引用元组的元素,很多讲师会在元组变量后附加索引。编写“带有索引n ”(指元组的第n个元素)的常用(LaTeX)表示法是_n
。所以我发现它实际上非常直观。
productIterator
以便在某些情况下可以使用更具体的类型。这可能是针对2.10版本的,但是如果我错了,有人可以纠正我。