scala - 类型模式匹配为什么变量是必须的

标签 scala pattern-matching expression generic-programming

我正在阅读“Scala for Impatient 2nd”第 14.4 节,我对上下文感到困惑:

You can match on the type of an expression, for example :

obj match {
   case x:Int => x
   case s:String => Integer.parseInt(s)
   case _:BigInt => Int.MaxValue
   case _ => 0
}

When you match against a type, you must supply a variable name. Otherwise, you match the object :

obj match {
   case _:BigInt => Int.MaxValue // Matches any object of type BigInt
   case BigInt => -1 // Matches the BigInt object of type Class
}

我感到困惑的是如何理解作为 expression 请求的 obj : 如果我测试如下:

val x = 121
val obj : Any = x
obj == 121 // true

obj match {
   case x:Int => x
   case s:String => Integer.parseInt(s)
   case _:BigInt => Int.MaxValue
   case _ => 0
} // res133: Int = 121

但是,如果我只是将整数值分配给 obj,编译器会抛出错误:

val obj2 = 121
obj2 == 121 // true

obj2 match {
   case x:Int => x
   case s:String => Integer.parseInt(s)
   case _:BigInt => Int.MaxValue
   case _ => 0
} // <console>:22: error : scrutinee is incompatible with pattern type;
found : String
required : Int
    case s : String => Integer.parseInt(s)
             ^    
<console>:23: error : scrutinee is incompatible with pattern type;
found : BigInt
required : Int
    case _ : BigInt => Int.MaxValue
             ^      

唯一的区别是前一个例子我给 obj 分配了另一个变量,而后一个例子我给 obj 分配了一个 Integer 值。为什么后一个例子会出现编译错误?

问题更新:我知道“编译器知道 obj2Int”,但是,我认为那是 匹配的 表达式适用于,i,e 因为 obj2Int 并且它满足第一个 match 子句 case x:Int => x 这样匹配成功,整个匹配表达式就完成了。我想这应该和前面的例子一模一样,唯一不同的是这两个变量是AnyInt类型,但是都匹配到了第一个match子句并且它们都应该被正确编译。

从本书第 14.4 节“在 Scala 中,这种(类型模式)匹配优于使用 isInstanceOf 运算符”,我认为使用类型模式是识别对象类型的一种方式。如果我们知道对象类型,那么“类型模式”有什么用?

第二个问题是我对下面的上下文感到困惑。如何理解“BigInt 类型的对象”与“Class 类型的 BigInt 对象”? “type Class”与 java generic/reflection 概念相关吗?

obj match {
   case _:BigInt => Int.MaxValue // Matches any object of type BigInt
   case BigInt => -1 // Matches the BigInt object of type Class
}

谢谢!

最佳答案

在第二种情况下,编译器知道 obj2Int,因此它知道不可能匹配 StringBigInt 可以成功。


编译时已知的和运行时已知的之间存在区别。您有以下代码:

val x = 121
val obj: Any = x

在运行时,xobj 都是 Int 并且将匹配您的 match 中的第一个 case表达。

在编译时,编译器知道 xInt,因此它知道没有必要测试 String大整数。它对 obj 的所有了解是它是 Any 因此可以检查 StringBigInt 或任何其他类型。

现在在这种情况下,很明显编译器可以计算出 obj 实际上是 Int,但在一般情况下这是不可能的。编译器没有关于类型推断的复杂规则,而是使用程序员赋予值的类型,即 Any。因此它假定 obj 可以是 StringBigInt,即使在这种情况下从代码中可以明显看出它不是。

关于scala - 类型模式匹配为什么变量是必须的,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56897884/

相关文章:

scala - 从案例类中提取给定类型的值

scala - 在 Haskell 中从左到右链接方法(而不是从右到左)

java - 从 Java (Scala) 调用 PHP 代码并获取结果

c# - C#7 中的 var 模式有什么好处?

r - 在 R 中拆分逗号和分号分隔的字符串

postgresql - 在 PostgreSQL-11 中有条件地更新字段时出错

scala - Intellij无法识别Scala List运算符

javascript数组解析匹配

javascript - 使用 PEG.js 的访问控制字符串 (ACS) 解析器/解释器

C++: "expected constant expression"