在scala中,我们可以得到一个元组上的迭代器,如下所示
val t = (1, 2)
val it = t.productIterator
甚至
it.foreach( x => println(x.isInstanceOf[Int]) )
返回true,我们不能在不使用asInstanceOf [Int]的情况下对迭代器值进行简单的操作,因为
it.foreach( x => println(x+1) )
返回错误:类型不匹配; found:Int(1)required:String
我理解Integer与Int的问题,但isInstanceOf [Int]的有效性仍有些令人困惑。
对元组进行这些操作的最佳方法是什么?请注意,元组可以混合使用带有双精度的整数类型,因此转换为列表可能并不总是有效。
答案 0 :(得分:3)
元组不必是同质的,编译器也不会尝试在元素 1 中应用魔术类型统一。以(1, "hello")
为例,说明这样一个异类元组(Tuple2[Int,String]
)。
这意味着x
的输入为Any
(不是Int
!)。尝试使用原始元组的it.foreach( (x: Int) => println(x) )
来获得更好的错误消息,指示迭代器不统一了元组元素的类型(它是Iterators[Any]
)。报告的错误应类似于:
error: type mismatch;
found : (Int) => Unit
required: (Any) => ?
(1, 2).productIterator.foreach( (x: Int) => println(x) )
在这种特殊情况下,isInstanceOf[Int]
可用于优化类型 - 来自类型系统提供给我们的Any
- 因为我们知道,来自手动代码检查,对于给定的元组,它将“安全”。
这是另一个涉及迭代器/类型的视图:
(1, 2) // -> Tuple2[Int,Int]
.productIterator // -> Iterator[Any]
.map(_.asInstanceOf[Int]) // -> Iterator[Int]
.foreach(x => println(x+1))
虽然我建议将元组视为有限元的同质元素而不是序列,但是在处理任何Iterator[Any]
时可以使用相同的规则,例如使用模式匹配(例如match
)区分实际对象类型。 (在这种情况下,代码使用隐式PartialFunction。)
(1, "hello").productIterator
.foreach {
case s: String => println("string: " + s)
case i: Int => println("int: " + i)
}
1 虽然有可能使编译器统一这种情况下的类型,但这听起来像是一个需要额外工作以获得最小收益的特殊情况。通常,列表(而不是元组)之类的序列用于同源元素,编译器/类型系统正确地为我们提供了一个很好的改进,例如List(1,2)
(按预期键入List[Int]
)。
答案 1 :(得分:1)
还有另一种类型HList,就像元组和List all-in-one。请参阅shapeless。
我认为,你可以接近你想要的东西:
import shapeless._
val t = 1 :: 2 :: HNil
val lst = t.toList
lst.foreach( x => println(x+1) )