8

我有一个关键字和运算符的枚举(以及其他一些),例如(都是相似的):

object Keywords extends Enumeration {
    val AND, ARRAY, BEGIN, ...= Value

    case class Keyword(keyword: Value) extends Token[Value] {
        def this(keyword: String) = this(Keywords.fromString(keyword))
        def value = keyword
    }

    implicit def valueToKeyword(keyword: Value) = new Keyword(keyword)
}

这种隐式转换允许我传递Token预期 s 的枚举值,例如

def testFunction[T](t: Token[T]) = ...
testFunction(Keywords.ARRAY) // gets converted
testFunction(Operators.PLUS) // gets converted too

似乎在匹配过程中也没有应用相同的隐式转换,即

val token = new Keyword("ARRAY")
token match {
    case Keywords.ARRAY => ... // not selected but SHOULD be
    case Operators.PLUS => ... // completely different Enum
    ...
}

为什么?如何克服这一点?

4

1 回答 1

5

这不起作用,因为:

token match {
  case Keywords.ARRAY => println("Array")
  case _ => println("Something else")
}

本质上是具有以下类型签名的PartialFunctionPartialFunction[Keywords.Value, Unit] : . 这意味着不会应用隐式,因为它要么是isDefinedAt要么不适用于该输入。

如果未定义,case _ => ...则将捕获我的示例代码中的所有内容。如果它根本没有定义并且没有任何东西匹配它,那么你会得到一个MatchError抛出。

在您的情况下token,类型Token[Value]未在匹配将编译到的部分函数中定义,因为只Keywords.Value定义了类型。

三种解决方案

如果你真的想要隐式,那么你可以明确地要求一个隐式(是的,那句话很有趣:))

implicitly[Keywords.Value](token) match {
  case Keywords.ARRAY => println("Array")
  case _ => println("Something else")
}

或者您可以显式声明 , 的类型token来调用隐式魔法:

val token: Keywords.Value = new Keyword("ARRAY")
token match {
  case Keywords.ARRAY => println("Array")
  case _ => println("Something else")
}

或者最简单的解决方案,如果你可以没有隐式生活:

token.value match {
  case Keywords.ARRAY => println("Array")
  case _ => println("Something else")
}

我知道这不是您要寻找的答案,但我希望您了解match {...}真正的含义以及偏函数是什么。

于 2013-11-12T00:20:27.987 回答