【问题标题】:How to I get rid of "unchecked due to erasure" warning when pattern matching模式匹配时如何摆脱“由于擦除而未检查”警告
【发布时间】:2011-11-15 23:26:27
【问题描述】:

Scala 2.8.1

我已经使用解析器/组合器实现了一个非常简单的外部 DSL,用于 QA 编写验收测试。

最近我添加了像这样循环一组表达式的功能

sealed trait Expr

...
//insert other case classes extending 'Expr' here
...

case class Repetition(times: Int, expressions: List[Expr]) extends Expr

class TestFixtureParser(....) extends RegexParsers {
  val repeatParser: Parser[Expr] = (l("repeat") ~> number) ~ (l("{") ~> expressions <~ l("}")) ^^ {
    case (times: Int) ~ (exprs: List[Expr]) => {
      Repetition(times, exprs)
    }
  }

  private val expressions: Parser[List[Expr]] = (repeatParser | 
    /*insert other Parser[Expr]s '|' together here */ | verifyParser ).*

}

在构建时,我在模式匹配时收到警告 warning: non variable type-argument ... is unchecked since it is eliminated by erasure。我也尝试过使用以下方法进行提取。

  //Doesn't build with error
  /*
    error: missing parameter type for expanded function ((x0$2) => x0$2 match {
      case $tilde((times @ _), (exprs @ _)) => Repetition(times, exprs)
    })
        r: ~[Int, List[Expr]] => {
  */
  val repeatParser: Parser[Expr] = (l("repeat") ~> number) ~ (l("{") ~> expressions <~ l("}")) ^^ {
    r: ~[Int, List[Expr]] => {
      case times ~ exprs =>
        Repetition(times, exprs)
    }
  }

  //Actually this does build without warning. 
  //I am unfortunately using intelliJ and it doesn't like it
  val repeatParser: Parser[Expr] = (l("repeat") ~> number) ~ (l("{") ~> expressions <~ l("}")) ^^ {
    repetitions: ~[Int, List[Expr]] => {
      val ~(times, exprs) = repetitions
      Repetition(times, exprs)
    }
  }

  //Builds but same warning
  val repeatParser: Parser[Expr] = (l("repeat") ~> number) ~ (l("{") ~> expressions <~ l("}")) ^^ {
    repetitions => {
      val ~(times: Int, exprs: List[Expr]) = repetitions
      Repetition(times, exprs)
    }
  }

有没有人有任何建议以优雅的方式提取exprs 而不会出现此警告?它按原样运行。我应该忽略它吗?我不想养成无视警告的习惯。

编辑:回答。这实际上是我首先尝试的,但后来我添加了类型,因为 intelliJ scala 插件无法推断它们。

  val repeatParser: Parser[Expr] = (l("repeat") ~> number) ~ (l("{") ~> expressions <~ l("}")) ^^ {
      case times ~ exprs =>
          Repetition(times, exprs)
  }

【问题讨论】:

  • 我很好奇的是为什么你的第一个“不构建”示例没有构建......我认为 Scala 将能够推断案例表达式中的类型。你得到什么错误?

标签: scala pattern-matching type-erasure parser-combinators


【解决方案1】:

我认为您的语法不适合第一个“不构建”示例(看起来您正在返回部分函数而不是应用它,这不是您想要的)。尝试 写作:

val repeatParser: Parser[Expr] = (l("repeat") ~> number) ~ (l("{") ~> expressions <~ l("}")) ^^ {
    case times ~ exprs =>
        Repetition(times, exprs)
}

恐怕我无法测试这个,因为我没有你的其余代码 取决于,但这种结构通常有效。

【讨论】:

    【解决方案2】:

    公认的答案是最好的,但是当它不起作用时,这里有替代方案:

    r: ~[t1, t2] => {
      case times ~ exprs =>
        Repetition(times, exprs)
    }
    

    以上,t1 和 t2 是推断的,它们可能只是推断为Any。然而,无论它们被推断为什么,这都是您可以使用该语法做的最好的事情。

    val ~(times: Int, exprs: List[t]) = repetitions
    

    在这里,因为您正在提取值,所以您实际上可以检查类型。您不是在测试是否有~[Int,List[Int]]——您是在测试提取的值是否具有Int 和List[t] 类型。请注意,您收到的警告来自List 的类型参数。

    【讨论】:

    • 是的,我完全明白擦除的事情。我在代码中的内容与接受的答案之间的唯一区别是我有明确的类型。问题是我暂时过于依赖 IntelliJ scala 插件。它用红色波浪线抱怨 ~ 的类型无法在那里推断。编译器另有说明。在过去 8 个月左右的时间里帮助我学习这门语言非常棒,但是随着我使用更高级的构造,重构工具和上下文帮助开始停止正常工作。
    • @drstevens 我不确定我们说的是同一件事。当我写~[t1, t2] 时,我非常准确:这里使用小写类型向编译器表明它应该推断类型,并将它们分配给t1 和t2。
    • 你说得对,我们说的不是同一件事。我不知道小写类型参数在这里有意义。我需要更多地了解这一点。感谢您的回复。
    • @drstevens 我自己花了两年多的时间才了解它,它非常晦涩难懂。注意 "here" 指的是模式匹配。它也不适用于 val 声明,除非它出现在模式内(如 val Some(t: ~[t1, t2]) = ...。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-01-25
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多