Thanks for the excellent example, I tried it and it works as I expected. Nice to see someone understood the nature of the problem. However, I think I should have tagged the problem with Lift as I'm using the Lift framework and that is where this problem is (still) occurring (although I still think it might be related to extraction in scala). Since I don't want to reproduce the entire Lift setup here as it will be too much code, I'm going to hope someone familiar with Lift can understand what I'm doing here. I've removed more variables so it might be 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 out the first case the second case is matched as expected.
For those 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 POST
I'm new to scala, so I may be doing something wrong here, but I have a pattern matching expression that seems to be skipped over. Here's 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's going on"); Empty
}
If I take out the first case expression, everything works as expected. I'm tempted to think this is a bug (https://issues.scala-lang.org/browse/SI-2337), but does anyone know of a workaround?
At the very least, change the last line:
case other => () => { println("not sure what's going on " + other); Empty }
and tell us what it prints
I just typed up an example which seems to be the same scenario you've got in your code, and it 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")
}
Which outputs Expected: bar
See if you can reproduce the bug in a self-contained example like this, so maybe we (or if it is a bug, the Scala Dev Team, can figure out what is going wrong :)
Note: Seems like I misread your question the first time, sorry for that. I'm not going to delete this part anyway, because it might be helpful to someone else.
When using pattern matching, the first case-statement that matches will be executed, and after that, the match is complete and all other case statements will be ignored!
Your problem here is, that the first statement
case req:Req =>
matches every instance of Req. After matching the first statement and executing its code, Scala just jumps out of the match expression because it is finished. The second case-statement would match, but it is never executed for any given instance of Req because the first one matches. As far as I remember, this is known as shadowing a case statement.
So move your second case statement before the first one, and you should be fine.
Note that this is why in pattern matching, the more specific match cases need to come first and the more general case statements have to go last.
This is indeed the bug you are referencing in the Scala bug tracker. Req is a non-case class with a companion extractor methods, so the bug manifests itself here. The workaround you introduced seems fine.
For those interested, here is a sample case where the bug manifests itself:
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")
Related
I have to perform some actions based on cases in a pattern matching block, but only for selective cases, and nothing to be done for remaining. So is it ok to just return () for remaining cases? Something like this:
val x = ....
val y = ....
(x, y) match {
case (Some(number), Some(text)) => {
......
}
case (Some(number), None) => {
......
}
case (_, _) => () // do nothing
}
Depends what you mean by "ok". If you are asking if it will compile, you can easily answer that question yourself, by running a few snippets in a REPL and find out, that you don't even need to return a unit. Something like this works just fine:
"foo" match {
"bar" => "baz"
"bat" => 1500
_ =>
}
If however by "ok" you meant whether it is a good idea, then the answer is "probably not". As mentioned in the comments, this is not type-safe and also purely side-effecting and not referentially transparent. There is likely a better way to do what you want.
It's generally ok, if all the cases in a match result in Unit (spelled () in Scala), to have a case result in () to preserve exhaustivity.
That said, in this case, where you require the first Option to be defined to do anything, I would probably express this as:
x.foreach { number =>
y match {
case Some(text) =>
??? // note that { } aren't required in match and ??? is idiomatic for "some code here"
case None =>
???
}
}
Then again, I particularly dislike pattern matching on Option, so ymmv.
I have been working with Scala for close to a year, but every now and then I come across a piece of code that I don't really understand. This time it is this one. I tried looking into documents on "scala methods with generic parameter type", but I am still confused.
def defaultCall[T](featureName : String) (block : => Option[T])(implicit name: String, list:Seq[String]) : Option[T] =
{
val value = block match {
case Some(n) => n match {
case i : Integer => /*-------Call another method----*/
case s : String => /*--------Call another method----*/
}
case _ => None
}
The method is called using the code shown below :
var exValue = Some(10)
val intialization = defaultCall[Integer]("StringName"){exValue}
What I don't understand in the above described code is the "case" statement in the defaultCall method.
I see that when the exValue has a value and is not empty, the code works as expected. But in case I change the exValue to None, then my code goes into the "case _ = None" condition. I don't understand why this happens since the match done here is against the "variable" which would be either an Integer or a String.
What happens here is that when you pass a None it will match on the second case, which "catches" everything that is not an instance of a Some[T]:
block match {
case Some(n) => // Will match when you pass an instance of Some[T]
case _ => // Will match on any other case
}
Note that None and Some are two different classes that inherit from Option.
Also, the variable match is only done if the first match succeeds, otherwise not. To achieve the type checking in the first match you could do:
block match {
case Some(n: Int) => // do stuff
case Some(n: String) => // do stuff
case _ => // Will match on any other case
}
Hope that helps
I am fairly new to scala and I am doing my assignment.
This is the code that I am using:
case EqNumC(l,r) => (interp(l),interp(r)) match{
case (NumV(s),NumV(x)) => if(s == x) BoolV(true) else BoolV(false)
case _ => throw InterpException("Value not found!")
}
When I run this code, it works fine and I get my result correctly. However this is somehow wrong. and I decided to make it better, by doing so:
case EqNumC(l,r) => (interp(l),interp(r)) match{
case (NumV(s),NumV(x)) => if(s==x) BoolV(true)
case (NumV(_),NumV(_)) => BoolV(false)
case _ => throw InterpException("Value not found!")
}
However When I run this I get this error:
Status: CompilationFailure
solution.scala:129: error: type mismatch;
found : Unit
required: Value
case (NumV(s),NumV(x)) => if(s==x) BoolV(true)
^
I don't see the problem here, because it's almost the same as the other one. How can I get rid of this problem and what is the best way to get this done?
The if control structure needs to come before the => when pattern-matching. When it comes after, the compiler sees an if without an else and infers it to be Unit (no return type).
It should look like this:
case (NumV(s),NumV(x)) if(s == x) => BoolV(true)
The first version works because if/else returns a value, but a single if does not.
I'm trying to match an Option, and test to see if it's a Some containing the object making the call. So the code I want to write looks like this:
methodReturningOption() match {
case Some(this) => doSomething()
case _ => doSomethingElse()
}
but that fails to compile, with the error
'.' expected but ')' found
I also tried using Some(`this`) which gives the error
not found: value this
I can make it work if I add a variable which refers to this
val This = this
methodReturningOption() match {
case Some(This) => doSomething()
case _ => doSomethingElse()
}
but that looks ugly and seems like an unpleasant workaround. Is there an easier way to pattern match with this as an argument?
I suppose you could try this:
methodReturningOption() match {
case Some(x) if x == this => doSomething()
case _ => doSomethingElse()
}
It looks like this is considered a special keyword and can't be used in that context.
Jack Leow's solution is probably the best - I'd recommend going with that since it's much more explicit. However as an alternative you can also create a variable point to 'this' using the following syntax. (Note the self => on the first line)
class Person { self =>
def bla() = methodReturningOption() match {
case Some(`self`) => ???
case _ => ???
}
}
This doesn't really answer the question, it's just a potential alternative syntax that may be useful to you.
I have an Iterable[String] representing the lines in a file and I'd like to find the first line in that sequence that matches a regular expression and return a numerical value extracted by the regex. The file is big enough that it wouldn't make sense to load the whole thing into memory and then call toString() or something, so I'll need to go through it a line at a time.
Here's what I have (it works):
val RateRegex : Regex = ".....".r
def getRate(source : Source) : Option[Double] = {
import java.lang.Double._
for(line <- source.getLines() ) {
line match {
case RateRegex(rawRate) => return Some(parseDouble(rawRate))
case None => ()
}
}
return None
}
This seems ugly to me. It feels very imperative and case None => () might as well be replaced with a comment that says "you're doing it wrong."
I think I want something like def findFirstWhereNonNone(p : Function[A,Option[B]]) => Option[B] where the collection's elements are of type A.
Are there built-in methods that would let me do this in a more functional way? Should I just write that method?
P.S. While I'm at it, is there an alternative to using java.lang.Double.parseDouble? Scala's Double class doesn't expose it.
P.P.S I've seen a lot of posts on SO suggesting that the Source API shouldn't be used in production, but they're all from 2008 and 2009. Is that still the case? If so, what should I use for IO?
Update
I now have:
import util.matching.Regex.Groups
for{line <- source.getLines()
Groups(rawRate) <- RateRegex.findFirstMatchIn(line)} {
return Some(parseDouble(rawRate))
}
return None
which feels a lot better to me.
EDIT: This third alternative ia quite neat:
source
.getLines()
.collectFirst{ case RateRegex(x) => x.toDouble}
Not sure if it's more functional, but you can use the behaviour of foreach/for-comprehensions on Options
def getRate(source : Source) : Option[Double] = {
for {line <- source.getLines()
rawRate <- RateRegex.findFirstIn(line)}
return Some(rawRate toDouble)
return None
}
This works too (quite similar to EasyAngel's answer):
source
.getLines()
.map{RateRegex.findFirstMatchIn(_)}
.filter{_.isDefined}
.map{_.get.group(0).toDouble}
.head
.toList
.headOption
The last three are a little ugly. The take(1) is to ensure we only evaluate up to the first match. The toList is to force the evaluation, and the headOption to extract the first value as Some() or None if there is none. Is there a more idiomatic way of doing this?
Here is one of the possible solutions:
def getRates(source : Source) = source.getLines.map {
case RateRegex(rate) => Some(rate toDouble)
case _ => None
} filter (_ isDefined) toList
Please note, that this function now returns now List[Option[Double]] of all found rates. It's also important, that Iterator remains lazy until I call toList
Update
As was asked in comments, here is solution, that returns only first occurrence:
def getRate(source : Source): Option[Double] = source.getLines.map {
case RateRegex(rate) => Some(rate toDouble)
case _ => None
} find (_ isDefined) getOrElse None