为什么Scala中的元组不能遍历?

Why can't tuples in Scala be traversed?

假设我创建一个 Tuple6:

val tup = (true, 1 , "Hello" , 0.4 , "World" , 0 )
tup: (Boolean, Int, String, Float, String, Int)

我可以使用 ._<position> 访问元组的元素 tup._1tup._2 等等。但是为什么

for (i <- 1 to 6)
     println(tup._i)

给我一个错误说

value _i is not a member of (String, Int, Boolean, String, Double, Int)

我知道明确指出 元组不可迭代,但是如果 ._1 有效,._i 不应该以同样的方式工作吗?

归结为类型

您希望 _<position> 等动态访问器具有什么类型?在一般情况下,唯一有效的是 Any。在像 Scala 这样的强类型语言中,这对于大多数用途来说是无用的。

好消息是问题 可以 以类型安全的方式处理 - 参见例如HList-style tuple handling in shapeless.

但是,标准 Scala 库中没有这样的机制(除非使用宏等繁重的元编程)。

对于元组,有一个 productIterator 方法可以让您有机会迭代元组的元素。但显然,这种迭代的每个元素都是 Any

类型

您可以提供一个 Iterator[U],其中 U 是元组类型 T1Tn 的最小上限。

implicit class FancyTuple2[T1,T2,U](private val tuple: (T1 with U,T2 with U)) extends AnyVal { 
  def iterator: Iterator[U] = Iterator(tuple._1, tuple._2)
}

你必须为你需要一个元组的每个元数编写(或生成)这个。

I understand that it is clearly stated that Tuples are not iterable, but if ._1 works , shouldn't ._i work the same way ?

为什么要这样做?在一种情况下,您正在调用方法 _1(确实存在),在另一种情况下,您正在调用方法 _i(不存在)。调用两种不同的方法通常 not "work the same way",尤其是当其中之一甚至不存在时。