【问题标题】:Scala : Compiler emits no warning when pattern matching against a sealed traitScala:当与密封特征进行模式匹配时,编译器不会发出警告
【发布时间】:2016-05-17 12:10:27
【问题描述】:

这是一个sn-p。模式匹配时,编译器不会发出警告。你知道任何解决方法吗?

当我忘记与SimpleExpr.ExprOtherExpr.Expr 进行模式匹配时,我希望编译器发出警告。这个结构允许我分解两个表达式树共有的节点(如If

trait Hierarchy {
  sealed trait Expr
}
trait If {
  this: Hierarchy =>
  case class If(cond: Expr, yes: Expr, no: Expr) extends Expr
}
trait Word {
  this: Hierarchy =>
  case class Word(name: String) extends Expr
}

object SimpleExpr extends Hierarchy with If with Word
//object OtherExpr extends Hierarchy with If with Integer

object Demo extends App {
  import SimpleExpr._
  def func(expr: Expr) = expr match {
    case If(cond, yes, no) => cond
    // compiler should emit warning
  }
}

【问题讨论】:

    标签: scala pattern-matching traits sealed


    【解决方案1】:

    因为sealed 不具有传递性,所以我不清楚缺少编译错误是否是错误。

    我注意到在match 表达式中添加另一个大小写会导致编译器发出“无法访问代码”警告。这是我修改后的代码:

    #!/usr/bin/env scala
    Demo.main(args)
    
    sealed trait Hierarchy {
      sealed trait Expr
    }
    trait If {
      this: Hierarchy =>
      case class If(cond: Expr, yes: Expr, no: Expr) extends Expr
    }
    trait Word {
      this: Hierarchy =>
      case class Word(name: String) extends Expr
    }
    
    object SimpleExpr extends Hierarchy with If with Word
    //object OtherExpr extends Hierarchy with If with Integer
    
    object Demo extends App {
      import SimpleExpr._
      def func(expr: Expr) = expr match {
        case If(cond, yes, no) => cond
        // compiler should emit warning
        case Word(name) => printf("word[%s]\n",name)
      }
      func(Word("yo!"))
    }
    

    这是我运行它时得到的结果:

    warning: unreachable code
    case Word(name) => printf("word[%s]\n",name)
    one warning found
    word[yo!]
    

    警告不正确,unreachable 代码正在执行中。

    case Word 行被注释掉时,我得到的是:

    scala.MatchError: Word(yo!) (of class Main$$anon$1$Word$Word)
        at Main$$anon$1$Demo$.func(demo.sc:21)
    

    但是,以下内容确实会发出所需的警告:

    #!/usr/bin/env scala
    Demo.main(args)
    
    sealed trait Expr
    case class Word(name: String) extends Expr
    case class If(cond: Expr, yes: Expr, no: Expr) extends Expr
    
    trait Hierarchy
    trait IfExpr {
      this: Hierarchy =>
    }
    trait WordExpr {
      this: Hierarchy =>
    }
    
    object SimpleExpr extends Hierarchy with IfExpr with WordExpr
    //object OtherExpr extends Hierarchy with If with Integer
    
    object Demo extends App {
      import SimpleExpr._
      def func(expr: Expr) = expr match {
        case If(cond, yes, no) => cond
        // compiler should emit warning
        // case Word(name) => printf("word[%s]\n",name)
      }
      // func(Word("yo!"))
    }
    

    这是我收到的警告:

    demo.sc:22: warning: match may not be exhaustive.
    It would fail on the following input: Word(_)
      def func(expr: Expr) = expr match {
                         ^
    

    【讨论】:

    • 那么,(确保)你同意这是一个错误吗?
    • 警告似乎是一个错误。另一个显然不是。
    • 我试图密封层次结构,但仍然没有“密封行为”。你是怎么弄到的?
    • 感谢您的关注和时间。我赞成你的回答。 (我还在寻找能够达到预期效果的方法所以我还没接受……也许有人会有创意)
    • 我发现注释掉定义“case class Word”不会导致编译错误,所以在 Hierarchy 中定义一个 trait 似乎并不强制以任何方式实现类。请参阅我修改后的答案以获取可能满足您需求的版本。
    【解决方案2】:

    我终于找到了达到预期效果的解决方案:

    trait Hierarchy {
      sealed trait Expr
      case class Unit() extends Expr
    }
    trait AddIf extends Hierarchy {
      case class If(cond: Expr) extends Expr
    }
    trait AddWord extends Hierarchy {
      case class Word(name: String) extends Expr
    }
    trait AddSymb extends Hierarchy {
      case class Symb(name: String) extends Expr
    }
    
    
    object AST1 extends Hierarchy with AddIf
    object AST2 extends Hierarchy with AddSymb with AddIf
    
    
    object TestMatch extends App {
      def match1(e: AST1.Expr) = e match {
        case AST1.If(cond) => 1
      }
      def match2(e: AST2.Expr) = e match {
        case AST2.If(cond) => 1
        case AST2.Unit() => 1
      }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-04-13
      • 1970-01-01
      • 2016-10-13
      • 1970-01-01
      • 2011-02-08
      • 2019-02-23
      相关资源
      最近更新 更多