yur*_*ura 70 scala tuples iterable-unpacking
在数学和计算机科学中,元组是元素的有序列表.在集合论中,(有序的)n元组是n个元素的序列(或有序列表),其中n是正整数.
因此,例如,在Python中,元组的第二项将通过访问t[1].
在Scala中,只能通过奇怪的名称进行访问t._2.
所以问题是,为什么我不能按照定义访问元组中的数据作为序列或列表?有什么想法或者还没有检查过吗?
Jea*_*let 90
斯卡拉知道元组的元数,因此能够提供像访问器_1,_2等等,如果你选择产生编译时错误_3的一对,例如.而且,这些字段的类型正是用作参数的类型Tuple(例如_3,Tuple3[Int, Double, Float]将返回a Float).
如果要访问第n个元素,可以编写tuple.productElement(n),但这样的返回类型只能是Any,因此丢失了类型信息.
Vla*_*dim 33
我相信以下摘录自"Scala编程:全面的循序渐进指南"(Martin Odersky,Lex Spoon和Bill Venners)直接解决了您的两个问题:
访问元组的元素
您可能想知道为什么您不能像列表元素那样访问元组的元素,例如,使用"pair(0)".原因是列表的apply方法总是返回相同的类型,但元组的每个元素可能是不同的类型:_1可以有一个结果类型,_2可以有另一个,依此类推.这些_N数字是基于1的,而不是从零开始,因为从1开始是由具有静态类型元组的其他语言设置的传统,例如Haskell和ML.
就语言语法而言,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)
Run Code Online (Sandbox Code Playgroud)
ten*_*shi 20
之间的一个很大的区别List,Seq任何收集和元组或者是在元组的每个元素都有它自己的类型,其中在列表中的所有元素都具有相同的类型.
而作为结果,在Scala中,你会发现类,如Tuple2[T1, T2]或Tuple3[T1, T2, T3],所以对于每一个元素,你也有类型参数.集合只接受1个类型参数:List[T].语法就像("Test", 123, new Date)只是语法糖Tuple3[String, Int, Date].而且_1,_2等等只是返回对应元素的元组上的字段.
Ale*_*ult 12
您可以轻松地实现无形:
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
Run Code Online (Sandbox Code Playgroud)
很多可用于标准的收集方法也可用于元组这样(head,tail,init,last,++并:::进行连结,+:并:+添加元素take,drop,reverse,zip,unzip,length,toList,toArray,to[Collection],...)
小智 7
使用正常的索引访问,可以使用任何表达式,如果索引表达式的结果保证在范围内,则需要花费一些精力在编译时检查.使它成为一个属性,并为(1, 2)._3"免费" 提供编译时错误.像元组中项目访问中只允许整数常量这样的事情将是一个非常特殊的情况(丑陋和不需要,有些人会说荒谬)并且还有一些工作要在编译器中实现.
例如,Python可以逃脱,因为它无法(无法)检查(在编译时,即)索引是否在范围内.
我认为这是类型检查.正如delnan所说,如果你有一个元组t和一个索引e(一个任意的表达式),t(e)就会给编译器没有关于访问哪个元素的信息(或者即使它是那个大小的元组的有效元素).当您按字段名称访问元素(_2是有效的标识符,它不是特殊语法)时,编译器会知道您正在访问哪个字段以及它具有哪种类型.像Python这样的语言实际上并没有类型,所以这对他们来说并不是必需的.