Scala:类型模式匹配期间的转发引用错误

Scala: Forward reference errors during type pattern matching

我想了解以下 Scala 代码生成的编译时错误:

class MyClass {
    def determineType(x:Any):String = {
        x match {
            case Int => "It's an int."
            case Float => "It's a Float."
            case CIn  => "It's a CIn without a specifier."
            case c:CIn => "It's a CIn with a specifier."
            case DIn=> "It's a DIn without a specifier." // Error:Cannot resolve symbol DIn
            case d:DIn=> "It's a DIn with a specifier."
            case _ => "It's something else."
        }
    }
    case class CIn()
    class DIn
} // End class definition

def determineType(x:Any):String = {
    x match {
        case Int => "It's an int"
        case Float => "It's a Float"
        case COut  => "It's a COut without a specifier." // Error: Wrong forward reference
        case c:COut => "It's a COut with a specifier."
        case DOut=> "It's a DOut without a specifier." // Error: Cannot resolve symbol DOut.
        case d:DOut=> "It's a DOut with a specifier."
        case _ => "It's something else."
    }
}

case class COut()
class DOut()

determineType的版本MyClass中,case class CIn和常规的class DIn都是在[=之后定义和声明的11=]。尝试匹配没有说明符变量的 DIn 时会生成符号解析错误。

在脚本范围内,我们类似地定义了一个 case class Cout 和一个常规的 class DOut。在 determineType 的脚本范围版本中,我们有两个不同的错误。第一个是在没有说明符的情况下引用 case class 类型 (Cout) 时生成的,它显示为 "Wrong forward reference"。第二个是在引用没有说明符的常规 class 类型(DOut)时生成的,它是符号解析错误。

我是该语言的新手,因此不确定为什么在 case 语句中包含说明符会影响前向引用的处理方式。

如果你写了一个匹配子句case Foo =>你匹配的不是类型(或class)Foo而是Foo。所以 case Int => not 匹配整数值,而 case DIn => 不起作用,因为没有值(或对象) DIn.

以下作品:

val Foo = 1
object Bar

def testVal(x: Any) = x match {
  case Foo => "it's Foo"
  case Bar => "it's Bar"
  case _   => "none of the above"
}

testVal(1)  // Foo!
testVal(Bar) // Bar
testVal(Foo + 1) // none

如果您想匹配 class 的实例,则需要匹配子句 case b: Baz =>case _: Baz(如果您对绑定实例不感兴趣一个值)。对于 case classes,您可以进一步使用自动提供的提取器,因此使用 case class Baz() 您也可以匹配为 case Baz() =>。当 Baz 包含特此提取的参数时,这通常更有意义:

case class Baz(i: Int)

def testType(x: Any) = x match {
  case Baz(3) => "Baz with argument 3"
  case b: Baz => "Baz with argument other than 3"
  case Baz    => "Baz companion!"
  case _      => "none of the above"
}

testType(Baz)     // companion object!
testType(Baz(3))
testType(Baz(4))

案例 class 也给你一个同伴 object 所以在这里你实际上可以使用 case Baz => 匹配那个对象。 object 是一种值。


最后,我不知道你使用的是哪个Scala版本,但是在当前的常规Scala中,你不能省略determineType定义的RHS上的match关键字:

def determineType(x: Any): String = {
  case _ => "anything"
}
<console>:53: error: missing parameter type for expanded function
The argument types of an anonymous function must be fully known. (SLS 8.5)
Expected type was: String
          def determineType(x: Any): String = {
                                              ^

你必须写:

def determineType(x: Any): String = x match /* ! */ {
  case _ => "anything"
}