首页 文章

对Scala元组的迭代[重复]

提问于
浏览
0

这个问题在这里已有答案:

在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) )

返回错误:类型不匹配;发现:Int(1)required:String

我理解Integer与Int的问题,但isInstanceOf [Int]的有效性仍有些令人困惑 .

在元组上执行这些操作的最佳方法是什么?请注意,元组可以混合使用带有双精度的整数类型,因此转换为列表可能并不总是有效 .

2 回答

  • 3

    元组不必是同质的,编译器不会尝试在elements1之间应用魔术类型统一 . 以 (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 - 因为我们知道,从手动代码检查,它将与给定元组一起"be safe" .

    这是另一个涉及的迭代器/类型:

    (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

    还有另一种类型HList,就像元组和List all-in-one . 见shapeless .

    我想,你可以接近你想要的东西:

    import shapeless._
    val t = 1 :: 2 :: HNil
    val lst = t.toList
    lst.foreach( x => println(x+1) )
    

相关问题