感谢这个优秀的例子,我尝试了它,它按照我的预期工作。很高兴看到有人理解问题的本质。但是,我认为我应该用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),但有没有人知道解决方法?
答案 0 :(得分:2)
至少,改变最后一行:
case other => () => { println("not sure what's going on " + other); Empty }
并告诉我们打印什么
答案 1 :(得分:1)
我刚刚输入了一个示例,它看起来与您在代码中的情况相同,并且在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")
}
哪个输出Expected: bar
看看你是否可以在这样一个自包含的例子中重现这个bug,所以也许我们(或者如果它是一个bug,Scala Dev Team,可以弄清楚出了什么问题:)
注意:似乎我第一次误读了您的问题,对不起。我不会删除此部分,因为它可能对其他人有帮助。
使用模式匹配时,将执行匹配的第一个case语句,之后匹配完成,所有其他case语句将被忽略!
你的问题是,第一个声明
case req:Req =>
匹配Req
的每个实例。匹配第一个语句并执行其代码后,Scala跳出匹配表达式,因为它已完成。第二个case-statement 将匹配,但它永远不会对Req
的任何给定实例执行,因为第一个匹配。据我记忆,这被称为shadowing
个案陈述。
所以在第一个案例陈述之前移动你的第二个案例陈述,你应该没事。
请注意,这就是为什么在模式匹配中,需要先提到更具体的匹配案例,而更常见的案例陈述必须持续。
答案 2 :(得分:0)
这确实是您在Scala错误跟踪器中引用的错误。 Req
是一个带有伴随提取器方法的非案例类,因此bug在此处显示出来。你介绍的解决方法似乎很好。
对于那些感兴趣的人,这里是一个bug表现出来的示例:
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")