通过间接索引获取匿名/未命名的元组值?

时间:2016-02-22 21:10:32

标签: scala tuples

注意这个

val oddOrEven = (odd, even)

oddOrEven._1会给出“奇数”,而oddOrEven._2会给出“偶数”

如果你愿意的话,我们基本上会得到一个“无名”成员的元组。

但我们假设我想得到奇数或偶数,取决于一些外部数据,如下:

val witness: Int = {numberOfPrevious % 2}

现在,让我们这样做:

val one = oddOrEven._witness

这不会编译。

是否涉及某些特殊语法或者这是不可能的?

我很好奇并且想知道编译器是否无法推断出witness的唯一可能值是0和1(但我认为这对我来说是愚蠢的,但我不得不尝试并尝试了这个:

val oddOrEven = (odd, even)
val witness: Int = {numberOfPrevs % 2}

val v = x match {
    case 0 => oddOrEven._1
    case 1 => oddOrEven._2
}

然而val one = oddOrEven._witness再次无效

然后我深入挖掘并发现编译器确实不会检查是否已耗尽。像:

val v = x match {
    case 1 => oddOrEven._1
    case 2 => oddOrEven._2
}

仍然可以编译,虽然2是不可能的,0却丢失了!

所以,我知道我在这里混合了一些东西。我知道有些匹配在我的mothertongue中不是所谓的“耗尽”,所以可能的值不是在编译时推断出来的,而是在运行时(实际上我会得到一个

  

scala.MatchError:0(类java.lang.Integer)   在运行时。

但是,我真正感兴趣的是:我可以通过“间接索引”来获取“未命名”元组吗?

3 个答案:

答案 0 :(得分:1)

你应该不这样做。如果您需要索引,请考虑ListVector

但是如果你真的想要这个并且所有的元组项都属于同一类型(例如Int)你可以这样做:

 (even, odd).productIterator.collect { case x: Int => 2* x }.toList(0)

答案 1 :(得分:1)

好吧,你可以做一些像tuple.productIterator.toList(index-1)这样的事情,但是如果你想要一个列表,那么只使用一个列表而不是将一个元组转换为它是一个更好的主意。

不,编译器不会试图弄清楚代码执行的所有可能方式,以便告诉变量可能采用的值。

答案 2 :(得分:1)

如何保持简单,如下:

val oddOrEven = (odd, even)
val witness: Int = {numberOfPrevious % 2} // Or any other calculation of index
oddOrEven.productElement(witness)

当productElement返回Any时,您会失去类型安全性,但是当您知道可以强制转换的成员类型时,例如:

oddOrEven.productElement(witness).asInstanceOf[YourType]

我在这里假设您的奇数和偶数值属于同一类型,例如:

sealed trait OddOrEven
case object odd extends OddOrEven
case object event extends OddOrEven

然后:

oddOrEven.productElement(witness).asInstanceOf[OddOrEven]

会给你正确的OddOrEven类型。

顺便说一下。看看ScalaDoc for Tuple2