如何解决Scala模式匹配大小写被跳过
| 感谢您的出色示例,我尝试了一下,它可以按预期工作。很高兴看到有人了解问题的本质。但是,我认为我应该在使用Lift框架时使用Lift标记问题,因此(仍然)仍在发生此问题(尽管我仍然认为这可能与scala中的提取有关)。由于我不想在这里重现整个Lift设置,因为这会太多代码,所以我希望熟悉Lift的人可以理解我在这里所做的事情。我已经删除了更多变量,因此(对于某些人来说)更容易发现问题:lazy val dispatch: LiftRules.dispatchPF = {
// Explicitly setting guard to false to trigger the scenario
case req: Req if false => () => println(\"shouldn\'t match\"); Empty
// This should match since prevIoUs case will never match
case Req(_,_,_) => () => println(\"should match\"); Empty
// This is actually called...
case _ => () => println(\"shouldn\'t reach here\"); Empty
}
和以前一样,如果我注释掉第一种情况,则第二种情况符合预期。
对于那些感兴趣的人,一个简单的解决方法是:
lazy val dispatch: LiftRules.dispatchPF = {
case req: Req => {
if (false) { // ObvIoUsly you put something more useful than false here...
() => println(\"shouldn\'t match\"); Empty
} else req match {
// This matches
case Req(_,_) => () => println(\"should match\"); Empty
// This is Now never called
case other => () => println(\"shouldn\'t reach here\"); Empty
}
}
}
原始帖子
我是Scala的新手,所以我在这里可能做错了什么,但是我有一个模式匹配表达式,似乎已被跳过。这是代码:
lazy val dispatch: LiftRules.dispatchPF = {
// Explicitly setting guard to false to trigger the scenario
case req: Req if false => () => Full(...)
// This should match since prevIoUs case will never match
case Req(\"api\" :: \"test\" :: Nil,suffix,GetRequest) => () => Full(...)
// This is actually called...
case _ => () => println(\"not sure what\'s going on\"); Empty
}
如果我取出第一个case
表达式,一切都会按预期进行。我倾向于认为这是一个错误(https://issues.scala-lang.org/browse/SI-2337),但是有人知道解决方法吗?
解决方法
这确实是您在Scala错误跟踪器中引用的错误。
Req
是带有附带提取器方法的非大小写类,因此该错误将在此处显示。您介绍的解决方法似乎很好。
对于那些感兴趣的人,这里是一个示例示例,其中的错误得以显现:
class Sample(val a: String)
object Sample {
def apply(a: String) = new Sample(a)
def unapply(s: Sample) = Option(s.a)
}
val s = new Sample(\"a\")
val r = s match {
case n: Sample if false => \"Wrong 1: \" + n
case Sample(_) => \"Yay\"
case n => \"Wrong 2: \" + n
}
println(\"Found \" + r)
assert(r == \"Yay\")
, 至少更改最后一行:
case other => () => { println(\"not sure what\'s going on \" + other); Empty }
告诉我们它打印什么
, 我只是输入了一个示例,该示例似乎与您的代码中的场景相同,并且可以在Scala 2.9中按预期工作:
case class Foo(x:String)
val bar = Foo(\"bar\")
bar match {
case x:Foo if false => println(\"Impossible\")
case Foo(x) => println(\"Expected: \" + x)
case _ => println(\"Should not happen\")
}
输出outputs8ѭ
看看您是否可以在这样的独立示例中重现该错误,也许我们(或者如果是错误,Scala Dev Team可以找出问题所在:)
注意:好像我是第一次误读您的问题,对此感到抱歉。无论如何,我不会删除此部分,因为它可能对其他人有帮助。
使用模式匹配时,将执行第一个匹配的case语句,然后,匹配完成,所有其他case语句将被忽略!
您的问题是,第一个语句
case req:Req =>
匹配Req
的每个实例。在匹配第一条语句并执行其代码之后,Scala会跳出匹配表达式,因为它已完成。第二个case语句可以匹配,但是对于任何给定的Req
实例都不会执行,因为第一个匹配。据我所知,这被称为“ 12”个案例陈述。
因此,将您的第二个案例声明移到第一个案例声明之前,就可以了。
请注意,这就是为什么在模式匹配中,更具体的匹配用例需要排在最前面,而更一般的case语句必须排在最后。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。