注意这个
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) 在运行时。
但是,我真正感兴趣的是:我可以通过“间接索引”来获取“未命名”元组吗?
答案 0 :(得分:1)
你应该不这样做。如果您需要索引,请考虑List
或Vector
。
但是如果你真的想要这个并且所有的元组项都属于同一类型(例如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