Unit
нельзя присвоить Tuple
val t: (Int, Int) = () // Error: type mismatch; found: Unit required: (Int, Int)
Однако следующий синтаксис представляет собой сопоставление с образцом
val (a: Int, b: Int) = ...
, который в вашем случае приводит к тому, что что-то подобное
val x: Any = 3 match {
case 3 => (1, 2)
case 4 => println("why")
}
val a: Int = x match {
case t: (_, _) if t._1.isInstanceOf[Int] => t._1.asInstanceOf[Int]
}
val b: Int = x match {
case t: (_, _) if t._2.isInstanceOf[Int] => t._2.asInstanceOf[Int]
}
Обратите внимание на те asInstanceOf[Int]
, которые убеждают тип компилятора c типа a
и b
равен Int
, однако, что произойдет во время выполнения это другая история. Например, рассмотрим
val t: (Int, Int) = println("why").asInstanceOf[(Int, Int)]
, который компилируется, но не работает во время выполнения.
Анализ -Xprint:jvm
вывода
lazy val (a: Int, b: Int) = (): Any
, мы имеем приблизительно
val t: Tuple2 = {
val x1: Any = ()
if (x1.isInstanceOf[Tuple2]) {
val x2: Tuple2 = x1.asInstanceOf[Tuple2]
val a: Any = x2._1
val b: Any = x2._2
if (a.isInstanceOf[Int]) {
val x3: Int = scala.Int.unbox(a) // in effect asInstanceOf[Int]
if (b.isInstanceOf[Int]) {
val x4: Int = scala.Int.unbox(b) // in effect asInstanceOf[Int]
new Tuple2(x3, x4)
} else throw new MatchError(x1)
} else throw new MatchError(x1)
} else throw new MatchError(x1)
}
def a: Int = t._1
def b: Int = t._2
, в то время как
lazy val (a: Int, b: Int) = ()
не компилируется, следовательно, если выражение справа от =
, в определении значения шаблона, набирает Any
, это имеет значение.