Scala pattern matching event skipped

Thanks for the great example, I tried, and it works as I expected. It's nice to see someone understand the nature of the problem. However, I think I should have noted the problem with Lift, since I use the Lift framework, and this is where the problem is (still) (although I still think this might be due to extraction in scala) . Since I don’t want to play the entire Lift installation here, since there will be too much code, I hope that someone familiar with the Lift will be able to understand what I am doing here. I deleted more variables to make it easier (for some) to see the problem:

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 } 

As before, if I comment on the first case, the second case will be as expected.

For those who are interested, a simple workaround is:

 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 } } } 

ORIGINAL MAIL

I'm new to scala, so I may be doing something wrong here, but I have an expression that matches the pattern, which seems to be missing. Here is the code:

 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 going on"); Empty } 

If I select the first case expression, everything will work as expected. I am tempted to think that this is a mistake ( https://issues.scala-lang.org/browse/SI-2337 ), but does anyone know of a workaround?

+4
source share
3 answers

This is really the error you are referring to in Scala bug tracking. Req is a non-case class with auxiliary extractor methods, so the error appears here. The workaround you entered seems wonderful.

For those who are interested, here is an example where the error appears:

 class Sample(val a: String) object Sample { def apply(a: String) = new Sample(a) def unapply(s: Sample) = Option(sa) } 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") 
0
source

At least change the last line:

 case other => () => { println("not sure what going on " + other); Empty } 

and tell us what it prints

+2
source

I just typed an example, which seems to be the exact same script that you have in your code, and works as expected in 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") } 

What are the outputs of Expected: bar

See if you can reproduce the error in a self-contained example, for example, like this, maybe we (or if this is an error, the Scala Dev team can find out what is going wrong :)

Note: It seems that I misunderstood your question for the first time, sorry for that. I still won’t remove this part because it might be useful to someone else.

When using pattern matching, the first case-statement match will be executed, after which the match will be completed, and all other case arguments will be ignored!

Your problem is that the first statement

 case req:Req => 

corresponds to each instance of Req . After matching the first statement and executing its code, Scala simply jumps out of the match statement because it is complete. The second case statement will match, but it never executes for any given Req instance, because the first one matches. As far as I remember, this is called a shadowing case case.

So, transfer your second case statement before the first, and everything will be fine.

Please note that this is why in comparison with the sample, more specific cases of coincidence should be the first, and more general cases should be the last .

+1
source

All Articles